Even more, when thinking about derived classes, you cannot override the
behaviour of fields, but you can using properties. It's totally clear that a
code like the following seems to add an extra overhead when you first look
at it:
class A {
Guid id;
public Guid Id {
get {
return id;
}
set {
id = value;
}
}
If you will never change that implementation and you will never derive from
that class, well, then you may use
class A {
public Guid id;
}
But, as already said in the previous postings, if you need to check the
field content or raise events or start a thread or whatever else you may
think of when the field changes, the only way is to use a property. The most
simple example for it is a class having some fields and you want to know if
an instance of this class is dirty, meaning that one ore more properties
were modified. Using fields instead of properties, you would certainly end
up using code like the following:
class A {
public Guid Id;
public string Name;
public decimal Price;
public Guid old_Id;
public string old_Name;
public decimal old_Price;
public bool IsDirty {
get {
return (old_ID != Id && Name != old_Name && Price != old_Price);
}
}
}
If you have a class with 20 or more properties, IsDirty will become slow and
you will likely forget to add new comparisons to it when adding new fields
to the class. Furthermore you have to store two values for each field to be
able to evaluate if the instance was modified.
Compare this solution to the follwing:
class A {
public Guid id;
public string name;
public decimal price;
public bool isDirty;
public Guid Id {
get {
return id;
}
set {
if (id != value) {
id = value;
isDirty = true;
}
}
public string Name {
get {
return name;
}
set {
if (name != value) {
name = value;
isDirty = true;
}
}
public decimal Price {
get {
return price;
}
set {
if (price != value) {
price = value;
isDirty = true;
}
}
public bool IsDirty {
get {
return isDirty;
}
}
}
As you can see, there is no need to store the original values to find out if
an instance has changed. Now let's say that the price must be positive, as
you usually have to pay for everything that you can buy. If you find someone
giving you money when you buy some items, please let me know. How do you
check that with public fields? You can't. Well, you could if you have a Save
method or something similar, that checks for valid values, but the problem
is that you never know the piece of code that actually stored the invalid
value. You will only know about it when you call the Save method, which
makes finding errors a lot harder. A much better approach is the follwing:
public decimal Price {
get {
return price;
}
set {
if (price <= 0) {
throw new ArgumentException("Price must be a positive
number.");
}
if (price != value) {
price = value;
isDirty = true;
}
}
Yeah, throw an exception. Exceptions are your friend not the evil :-)
Last example: You have a class B deriving from class A and you don't want to
allow the price to be lower than 20. Can you do this check with public
fields? No, you can't. But you can with properties. Simply add the virtual
keyword to the Price property in class A:
public virtual decimal Price {
...
}
and in class B do the following:
class B : A {
public override decimal Price {
get {
return base.Price;
}
set {
if (price <= 20) {
throw new ArgumentException("Price must be at least 20
bucks.");
}
base.Price = value;
}
}
Whatever code you have implemented in class A will be executed through the
base.Price calls but you're also able to extend the logic (in this case the
comparsion >= 20).
If you still want to use public fields, go for it. Noone will stop you from
doing it and if you're very careful your application will work. However,
properties will help you in structuring your code and allow to write code at
exactly the place where it belongs. Ok, you need to add a few lines to add
the accessors, but it's worth it.
Need a last example? Try to implement a read-only field :-)
Michael
"Peter Rilling" <pe***@nospam.rilling.net> schrieb im Newsbeitrag
news:ue**************@tk2msftngp13.phx.gbl...
Another reason might be to validate the data. For instance, suppose you
have a property that is an integer, but you only accept values in a
certain range. Well, before you set your private variable, you can check
the value and, maybe, throw an exception if the value is incorrect.
<mi************@gmail.com> wrote in message
news:11**********************@g43g2000cwa.googlegr oups.com... It's best practice to even use the Property Assessors from code private
to your class. Don't directly access your private member variables.
This protects you from forgetting that a property has code executing in
it or when you have to add code the accessor you don't have a large
refactor job.
You should not:
if (m_MyVar)
You Should:
if (MyVar)
public void MyVar
{
get{return m_MyVar;}
set{m_MyVar = value;}
}