Good practices with Properties

  • Thread starter Thread starter James Thurley
  • Start date Start date
J

James Thurley

I'm having a problem figuring out the best way to use Properties in my
code. Here are the 'good practices' I have in my head:

1) Variables should always be accessed through Properties where possible
in case you need to add, for example, some checking code or whatever
later on.

2) A class should always give copies of its internal objects to external
classes to stop it being corrupted.

For example:

class A{
private Font f;
public Font F{
get{return f;} // Returns reference to internal object
set{
/*Checking code here*/
f=value;
}
}
}

class B{
private Font f;
public Font F{
get{return (Font)f.Clone();} // Returns copy.
set{
/*Checking code here*/
f=value;
}
}
}

class C{
void func(A a, B b){
Font f1 = a.F;
Font f2 = b.F;
f1.Size = f2.Size = 100;
}
}

In the above code class C has bypassed the checking code for the Font
object in class A, but class B is safe.

That's all fine, but what if I have a class derived from class B:

class B2 : B{
public void FrequentDraw(){
/* Code to draw stuff which uses property F */
}
}

Where FrequentDraw() is called many times a second. Here the fact that
F has to copy the Font object each time will become a significant overhead.

I basically want to know what people think should be done in this
situation?

- Should I simply make the f object protected and access it directly,
even though this is 'bad practice'?
- Should I modify the property to return a reference, although this
makes the class less safe and makes my coding inconsistent.
- Should I create a second protected Property called something like
FRef which returns a reference, although this makes the code messy.

Or is there some better way I'm missing?

I have run benchmarks on code returning copies of objects, and while the
overhead is often not significant with small objects, it is highly
significant with more complex ones like the Font object when done
frequently.

Thanks,
James.
 
Hi, I have issues with properties, I think that how C# uses them and how
properties are implemented in the framework library (in particular Windows
Forms) are a source of bugs. I'll give my list at the end after going
through yours.

James said:
I'm having a problem figuring out the best way to use Properties in my
code. Here are the 'good practices' I have in my head:

1) Variables should always be accessed through Properties where
possible in case you need to add, for example, some checking code or
whatever
later on.

in general, yes, even if the properties are simply getter/setters (ie no
other validation).
2) A class should always give copies of its internal objects to
external classes to stop it being corrupted.

It all depends on your code. If you make a copy to return then in general
the property should be read only (ie only a get) to indicate that the client
cannot change the internal field. If a setter is needed then make sure you
document that the getter returns a clone.
I basically want to know what people think should be done in this
situation?

- Should I simply make the f object protected and access it
directly, even though this is 'bad practice'?
- Should I modify the property to return a reference, although this
makes the class less safe and makes my coding inconsistent.
- Should I create a second protected Property called something like
FRef which returns a reference, although this makes the code messy.

Or is there some better way I'm missing?

If you know that the getter will be called many times then return the
reference instead.

my other issues with properties are:

1) make sure that you do *not* give the property the same name as its type.
(Eg don't do the same as Control.Size which is a Size type). Having the name
the same as the type is OK for C# but causes problems with managed C++ (and
shows a lack of imagination on your part <g> !)

2) if a property getter/setter raises an event make sure you document this.
The reason is that the event may change another property on the object that
may caused unexpected effects.

3) C# properties are difficient because a setter cannot return a value, so
if x is a property on class T, you cannot do this:

T t1 = new T();
T t2 = new T();

t1.x = t2.x = 42;

the reason is that the setter on t2 is called and this will not return a
value to be passed into t1.x. If the class is written in C++ the setter
*can* return a value.

4) C# propeties cannot have different access level on getter and setter (in
C++ this *is* possible). For example, you might want to make the getter
public and the setter protected so that only the class, or derived classes
can change the property.

5) *please* avoid the horrible case that occurs with Width, Height,
Location, Size, Left, Right, Top, Bottom etc properties on the windows forms
Control. All of these properties affect the same internal fields and the
setters result in changing these fields with a single, multipurpose method
(SetBounds). Thus if you change the form like this:

Left = 100;
Top = 300;
Height = 200;
Width = 200:

SetBounds is being called *4 times*. Instead, just call SetBounds once:

SetBounds(100, 300, 200, 200);

If you only want to change the location (Left, Top) then use the overload
with BoundsSpecified:

SetBounds(100, 300, 0 , 0, BoundsSpecified.Location) // only the first two
params are valid

A better design for Control would have been if the size/location properties
were read-only, so that you can only change the size/location with a call to
SetBounds().

Richard
 
4) C# propeties cannot have different access level on getter and setter (in
C++ this *is* possible). For example, you might want to make the getter
public and the setter protected so that only the class, or derived classes
can change the property.

Fortunately this is going to change for the next version of C#/.NET, I
believe.
 
Back
Top