tags:

views:

240

answers:

9

I have the following class

  public class UIControl
  {
    public string FName{ get; set; }
    public HtmlInputCheckBox SelectCheckBox { get; set; }
    public bool OverrideSelect { get; set; }

    //Want to throw an ApplicationExceptioh if developer uses this constructor and passes
    //chkSelect = null
    public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
    {
      this.FName= sFieldName;
      this.SelectCheckBox = chkSelect;
    }

    public UIControl(string sFieldName, HtmlInputCheckBox chkSelect, bool overrideSelect)
      : this(sFieldName, chkSelect)
    {
      OverrideSelect = overrideSelect;
    }
  }

I want to make sure that the developer uses the first constructor only when chkSelect is not null.

I want to do a:

throw new ApplicationException("Dev is using the incorrect constructor");
+3  A: 

Whats hard?

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
{
    if (chkSelect == null)
    {
        throw new ApplicationException("Dev is using the incorrect constructor");
    }

    this.FName= sFieldName;
    this.SelectCheckBox = chkSelect;
}
abelenky
The 2nd constructor calls the 1st one, so if i check for chkSelect == null then it will throw an exception even when they have the OverrideSelect set
DotnetDude
I love how three people post the exact same code in less than 30 seconds... ;)
Tomas Lycken
Then you will need to modify the second constructor so that it doesn't use the first constructor. The constructor #2 has different rules than #1, and therefore cannot use #1.
abelenky
I posted a separate updated answer that shows how to separate the two constructors so that one allows a potentially null chkSelect, while the other does not.
abelenky
Should be an ArgumentException, not an ApplicationException
Rex M
OP wrote that he wanted ApplicationException, so I stuck with that.
abelenky
+3  A: 

Like this?

//Want to throw an ApplicationExceptioh if developer uses this constructor and passes
//chkSelect = null
public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
{
  if (chkSelect == null)
  {
    throw new ArgumentException("chkSelect cannot be null when using this constructor");
  }
  this.FName= sFieldName;
  this.SelectCheckBox = chkSelect;
}
Scott Anderson
I love how three people post the exact same code in less than 30 seconds... ;)
Tomas Lycken
+1  A: 

Why not like this?

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
{
    if (chkSelect == null) 
    { 
        throw new ApplicationException("Dev is using the incorrect constructor"); 
    }
    this.FName= sFieldName;
    this.SelectCheckBox = chkSelect;
}

However, it is probably a bad idea to do this via a runtime error. A better idea is to use an overload that doesn't take the chkSelect argument at all, or to make chkSelect non-nullable.

EDIT: I noticed now that the second selector calls the first one, but the only thing the second one does is change the value of the OverrideSelect field. Why not just have one constructor, and set that field? Or why have that field at all? A couple of alternatives:

// This is now the ONLY constructor you need
public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
{
    OverrideSelect = (chkSelect == null);
    this.FName= sFieldName;
    this.SelectCheckBox = chkSelect;
}


// You could solve it differently by replacing OverrideSelect with this property:
public readonly bool isChkSelectNull {
    get {
        return (this.chkSelect == null);
    }
}

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
{
    this.FName= sFieldName;
    this.SelectCheckBox = chkSelect;
}
Tomas Lycken
How can you make chkSelect non-nullable (except by redefining it as a struct type)??
ChrisW
This might be quite a lot of work if you're only going to use it this once, but it looks promising and reusable: http://blog.johannesh.dk/2008/10/how-to-make-non-nullable-type-wrapper.html
Tomas Lycken
+13  A: 

You can use a private constructor thus:

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect) 
    : this(sFieldName, chkSelect, false, false)
{      
}    

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect, 
     bool overrideSelect)      
    : this(sFieldName, chkSelect, overrideSelect, true)    
{      
}  

private UIControl(string sFieldName, HtmlInputCheckBox chkSelect, 
   bool overrideSelect, bool allowOverride)      
{      
    if ((!allowOverride) && (chkSelect == null)) 
         throw new ArgumentException(...);
    this.FName= sFieldName;      
    this.SelectCheckBox = chkSelect;    
    OverrideSelect = overrideSelect;    
}

There are lots of variants, but as a general rule, have less specific constructors calling more specific ones. For example, the following would also work in your case:

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)    
    : this(sFieldName, chkSelect, false)
{      
   if (chkSelect == null) throw ...
}    

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect, 
     bool overrideSelect)    
{      
    this.FName= sFieldName;      
    this.SelectCheckBox = chkSelect;    
    this.OverrideSelect = overrideSelect;    
}
Joe
A: 

Get Spec# or Contracts from .Net 4.0 and make the parameter non-nullable

Matthew Whited
A: 

Based on updated info from the OP:

public class UIControl
{
    //Want to throw an ApplicationException if developer uses this constructor and passes
    //chkSelect = null
    public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
    {
      if (chkSelect == null)
      {
        throw new ApplicationException("Dev is using the incorrect constructor");
      }
      this.FName= sFieldName;
      this.SelectCheckBox = chkSelect;
    }

    public UIControl(string sFieldName, HtmlInputCheckBox chkSelect, bool overrideSelect)
    {
      this.FName= sFieldName;
      this.SelectCheckBox = chkSelect;  // note: chkSelect MAY be null here.

      OverrideSelect = overrideSelect;
    }
  }
abelenky
A: 

I'm not a big fan of throwing Exceptions for programmer issues. Instead of throwing the Exception, how about Debug.Assert().

Chris Brandsma
A: 

Why should you throw an exception if chkSelect is null?

Anyways, to answer what you asked (not what necessarily what you really need), I think you might be doing it backwards. Have the 2 parameter version call the 3 parameter version.

//Want to throw an ApplicationExceptioh if developer uses this constructor and passes
//chkSelect = null
public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
  : this(sFieldName, chkSelect, chkSelect==null)
{
  if(chkSelect==null) throw new ArgumentNullException("chkSelect");
}

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect, bool overrideSelect)    
{
  this.FName= sFieldName;
  this.SelectCheckBox = chkSelect;
  OverrideSelect = overrideSelect;
}
dss539
thank's for catching my thow (hah, get it? :P ) Sorry I didn't load up the IDE to type it. In any case, chkSelect==null very much is what I intended to write. Why do you believe this won't work? Can you please teach me?
dss539
my mistake. chkSelect == null in the parameter is a valid boolean. I first read it as an attempt at a parameter with a default value.
abelenky
+2  A: 

It's a better practice (or more common practice, since C# doesn't have default parameters until 4.0) to have less specific constructors use the more specific constructors, and not vice versa. You can then utilize a private constructor with a nullable bool. If you are able to rewrite them, try the following:

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect)
  : this(sFieldName, chkSelect, null)
{
}

public UIControl(string sFieldName, HtmlInputCheckBox chkSelect, bool overrideSelect)
  : this(sFieldName, chkSelect, overrideSelect)
{
}

UIControl(string sFieldName, HtmlInputCheckBox chkSelect, bool? overrideSelect)
{
  if (!overrideSelect.HasValue && chkSelect == null)
  {
      throw new ArgumentException("chkSelect");
  }
  FName = sFieldName;
  SelectCheckBox = chkSelect;
  OverrideSelect = overrideSelect ?? false;
}
Jason