Properties best practice?

  • Thread starter Thread starter Jon Poploskie
  • Start date Start date
J

Jon Poploskie

Hello,

I am looking for opinions on property vs. (instance) variable use within a
class. Say I have the following class:

public class Dog
{
private string _name;
private string _breed;

public string Name
{
get { return _name; }
set { _name = (value == null ? "spot" : value; ) }
}

public string Breed
{
get { return _breed; }
set { _breed = value; }
}

public Dog(string name, string breed)
{
// how to set??
}
}

My question is, what is the best practice for using properties or variable
INSIDE the class in which they're defined? For example, in the constructor
above, should it look like:

{
_name = name; (or _name = (name == null ? "spot" : name; )
_breed = breed;
}

or

{
Name = name; // use property
Breed = breed; // use property
}

Is there a general rule, or does it depend on the semantics of where it's
being set (should _name automatically be set to "spot" in the constructor?),
or???

Thank you all for your input.
Jon
 
Inside, use the private variable, which is not externally available. It is
clearer, and is less likely to get you into trouble.

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA
Author: ADO.NET and XML: ASP.NET on the Edge

****************************************************************************
****
Think Outside the Box!
****************************************************************************
****
 
Typical property validation code may depend on the object instance being in
a valid state. During construction an object is not in a "valid" state
(until constructor code returns sucessfully to caller). So, typically set
the internal members in the constructors directly. If the constructor
arguements are not valid typically it should raise an ArgumentException.

However there is nothing preventing you from setting the properties during
construction. And it is perfectly legal to do so. Just be sure the first
ones set do not depend on the following ones to be initialized... IE.

public class Dog
{
... untested code, typed on the fly ...
private string _name; private string _regName;
public string Name{get{return _name;}set{_name = value;}}
public string RegisteredName
{ get{return _regName;}
set
{
// imagine some other validation that depends on Name ...
if (value == null || value.Length <= 0){_regName = this.Name;}
else{_regName = value;}
}
}
public Dog(string name, string regName)
{
//this order is ok...
this.Name = name;
this.RegisteredName = regName;

//this order is bad since regName depends on/relates to Name
this.RegisteredName = regName;
this.Name = name;

//if internal members are set directly then do different validation
unique from property set...
if (_name == null || _name.Length <=0){throw new
ArgumentException("name");}
_name = name;
if (_regName == null || _regName.Length <=0){throw new
ArgumentException("regName");}
_regName = regName;
}
}

I've found that at construction I have different validation than
afterwards... sometimes more, sometimes less. So I don't use the properties
in the consturctor. If you do use the properties, you must make sure that
each does not depend on any others set after itself. Since you write the
whole class it doesn't really matter...

My personal rule is that I only work with non-public members in the
constructor. In writing those, I can assume those are being used only as
intended. I always assume public members are being called by a consumer and
act accordingly.

You may also want to supply overloaded constructors so that they don't have
to specify values for arguements that they want to use the default value
for...

public Dog(string name, string breed)
{
_name = name; _breed = breed;
}
public Dog(string name)
{
_name = name; _breed = "ADefaultValue";
}
public Dog()
{
_name = "ADefaultOrAutoAssignedName"; //"UnNamed", "Spot", "Dog1",
"Dog2", whatever...
_breed = "ADefaultValue";
}
 
Agree with Cowboy and Michael. But, in your code:

set { _name = (value == null ? "spot" : value; ) }

There is no need to do "value==null?...", or "value==null?..." does not do
what you intent to do. Because you define this property as String type, you
cannot pass an object that is null to "value" argument here. It must be
casted to string before assigning to the property. I guess, your intention
is to test whether it is a null string or not. So, you should:

set { -name= (value == "" ? "spot" : value); } or set { -name= (value.Length
== 0 ? "spot" : value); }
 
Norman Yuan said:
Agree with Cowboy and Michael. But, in your code:

set { _name = (value == null ? "spot" : value; ) }

There is no need to do "value==null?...", or "value==null?..." does not do
what you intent to do.

I believe it does, although I would personally say that if a property
is set with a value of null, it should either accept that value or
throw an exception - making null a sort of "give me a default value"
idea is pretty strange.
Because you define this property as String type, you
cannot pass an object that is null to "value" argument here.

Yes you can. String is a reference type.
It must be casted to string before assigning to the property.

Eh? Why would any casting be involved?
I guess, your intention
is to test whether it is a null string or not. So, you should:

set { -name= (value == "" ? "spot" : value); } or set { -name= (value.Length
== 0 ? "spot" : value); }

That's testing for a reference to an *empty* string, which is different
from a *null* string reference.
 
Back
Top