Skip to main content
GameDev.net gamedev.net
🔒 Locked

Pros/Cons for Accessing class members - C#

Started by JSelf Jan 16, 2011 at 4:10 AM 14 replies 5.3k views
Original Post
JSelf
JSelf
Those of you who program in C# most likely know of the short cut to creating class properties without private fields, like so:

public int Count
{
get;
set;
}

Obviously, doing so eliminates the need for the programmer to create private fields as VS will do it for you (results in cleaner code, etc). With that said, none of the XNA tutorials I've been reading do so. Plus, they always access the member data through the private field ( _count) instead of the property (this.Count).

I was hoping some more experienced developers could lend some insight as to why. Is it just preference? Or something else that I'm just not aware of?

Also, how do you generally do it? This is assuming, of course, that the members are public and not private/protected.

Thanks for your time.

-Justin
ApochPiQ
ApochPiQ
IMHO, the code you've posted exhibits a pretty pungent code smell. Empty getters and setters on a public property just makes no sense; make it a public member variable directly and be done with it. Better yet, design your interface such that you don't need to expose state publicly in the first place.
HydroxicAcid
HydroxicAcid
Perhaps the tutorials you have been reading were written before C# had automatic properties. It was not part of the language until version 3.0. Personally, I prefer to use the automatic properties unless I want to set a property to a default value without cluttering up the constructor.
deepdene
deepdene
Another feature of automatic properties


class A
{
public int B { get; private set; }
}


Is causes your set to be private (only the current class can change the value) while allowing outside classes to get the value. Microsoft recommend that [font="'Segoe UI"]for [/font]small classes or structs that just encapsulate a set of values (data) and have little or no behaviors to make the objects immutable by declaring the set accessor as private http://msdn.microsoft.com/en-us/library/bb383979.aspx

Automatic properties just automatically behind the scenes add a private variable then have a default get/set method for that variable. It allows you to later on change it from being automatic to having a custom setter etc. This reduces your code modifications at later stages. i.e. outside classes don't have to be rewritten only the current class.
deepdene
deepdene
BTW automatic properties are the equivalent to the following just to clarify those who haven't seen this newer language feature.


class A
{
private int x;

public int X
{
get
{
return this.x;
}

set
{
this.x = value;
}
}
}


is equivalent to :


class A
{
public int X { get; set; }
}
Rainweaver
Rainweaver

IMHO, the code you've posted exhibits a pretty pungent code smell. Empty getters and setters on a public property just makes no sense; make it a public member variable directly and be done with it. Better yet, design your interface such that you don't need to expose state publicly in the first place.





You tend to hide interface consumers from changes as much as possible not to break things. You also don't want to expose public member variables very often, unless you're creating simple types such as a Point, or Vector, which for a number of reasons benefit from being as simple as they can, and also exist to merely store state.




It really boils down to the degree of modularity you're aiming for. Automatic properties (which are not "empty") are a commodity for people programming against interfaces.

dilyan_rusev
dilyan_rusev
It's already been explained: this syntax is nothing but synthetic sugar. The compiler generates backing fields, and you can verify that with Reflector.

Accessing the backing field directly or its encapsulating property is.. arguable.
If you access directly the field, your code will run a little bit faster, because you won't have to invoke a function, but {get;set;} properties are just 3/4 IL instructions, so your users won't notice any difference.Also, using the property only as a wrapper around the field with no logic attached to it is a little bit too much.
If you access directly your property, and not the backing field, you get the benefit of abstraction. It is common in .NET to have private properties that encapsulate common logic as a field. You can do late initialization, caching of some expensive operation, etc - and the code using that property won't actually care as long as it works.

My preference is to access the property instead of the field. You should have in mind that real-world scenarios sometimes require that you use normal backing fields. For example, some serializers and ORMs use fields and not properties for serialization, and your database/xml storage might end up looking ridiculous.

@ApochPiQ
I am not that competent in game development, but properties are the key to component-driven development. With properties, you can take advantage of ASP.NET's template parser treating properties as attributes/inner elements, thus getting some free serialzation and declarative customization. There are also the property descriptors/converters/validators that enable you to associate a lot of meta information to a property, in effect making your API quite naturally extensible. I, too, agree that having having properties that act solely as public fields with no logic attached to them is a little bit pointless.
ApochPiQ
ApochPiQ
I have no problem with properties per se; in fact they're very useful for introducing certain types of logic and semantics. But empty properties are worthless.

Consider: in C#, the syntax foo.Field will work to access Field whether Field is a public member or a property. So the best course of action is to begin with public fields, and if you need to refactor to add logic later, drop in a property named Field with the associated logic. No calling code needs to be changed, meaning you only have minor code site updates to make, and everything continues to work swimmingly.

Of course, I stand by my argument that avoiding public state is far superior as a design philosophy anyways.
SiCrane
SiCrane

Consider: in C#, the syntax foo.Field will work to access Field whether Field is a public member or a property. So the best course of action is to begin with public fields, and if you need to refactor to add logic later, drop in a property named Field with the associated logic. No calling code needs to be changed, meaning you only have minor code site updates to make, and everything continues to work swimmingly.

The syntax is the same, but the generated MSIL is different. This means that if you change from a public field to property, you can't do a drop in binary replacement. Calling code still needs to be recompiled.
m_switch
m_switch

[quote name='ApochPiQ' timestamp='1295203640' post='4759727']
Consider: in C#, the syntax foo.Field will work to access Field whether Field is a public member or a property. So the best course of action is to begin with public fields, and if you need to refactor to add logic later, drop in a property named Field with the associated logic. No calling code needs to be changed, meaning you only have minor code site updates to make, and everything continues to work swimmingly.

The syntax is the same, but the generated MSIL is different. This means that if you change from a public field to property, you can't do a drop in binary replacement. Calling code still needs to be recompiled.
[/quote]

Note that the semantics of properties and public variables that return value types are different. For public variables, you are directly accessing the variable. However, a property that returns a value type makes a copy of the variable.
TheTroll
TheTroll
I am a huge fan of properties. Why? Because if you use them as a single way to change values in your class then you have a toll bridge into that data. It is the one place that you can verify before you change the core data that what you are changing will not break the application. It is the sanity check for the class. You can verify that your data will never be invalid. That is what I use them for.
deepdene
deepdene

Note that the semantics of properties and public variables that return value types are different. For public variables, you are directly accessing the variable. However, a property that returns a value type makes a copy of the variable.



[font="arial, verdana, tahoma, sans-serif"]In both instances with value types the values are placed onto the evaluation stack and popped into the appropriate stack variable.

Our class definition and code we are basing this MSIL off:[/font][font="arial, verdana, tahoma, sans-serif"]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class A
{
public int x;

public int X
{
get
{
return this.x;
}

set
{
this.x = value;
}
}

public int J { get; set; }
}

class Program
{
static void Main(string[] args)
{
A a = new A();

a.x = 22;

int x = a.x;

a.X = 32;

x = a.X;

int j = 0;

a.J = 22;

j = a.J;

}
}
}


Here's the difference in MSIL between accessing the property and the field. [/font]


.

maxstack 2
.locals init
(
[0] class ConsoleApplication1.A a,
[1] int32 x,
[2] int32 j
)

// Load the class onto the evaluation stack
L_000f: ldloc.0


// Load the value from the field onto the evaluation stack
L_0010: ldfld int32 ConsoleApplication1.A::x
// Pop the value from the evaluation stack into the local stack variable
1L_0015: stloc.1

// Now property example
// Load the class onto the evaluation stack
L_001f: ldloc.0
// Call a late bound method on the object on the top of the evaluation stack pushing the return value onto the evaluation stack
L_0020: callvirt instance ConsoleApplication1.A::get_X()
// Pop the value from the evaluation stack into the local stack variable
L_0025: stloc.1



Also the only difference between a automatic property and providing the backing field yourself in terms of MSIL is the fact that the compiler adds an attribute to the field I believe to indicate it's compiler generated.
m_switch
m_switch

[quote name='m_switch' timestamp='1295206621' post='4759746']
Note that the semantics of properties and public variables that return value types are different. For public variables, you are directly accessing the variable. However, a property that returns a value type makes a copy of the variable.



[font="arial, verdana, tahoma, sans-serif"]In both instances with value types the values are placed onto the evaluation stack and popped into the appropriate stack variable.

...[/font]

Also the only difference between a automatic property and providing the backing field yourself in terms of MSIL is the fact that the compiler adds an attribute to the field I believe to indicate it's compiler generated.
[/quote]

This is an implementation detail, I was speaking in reference to the semantics. Visual Studio will actually generate an error when you attempt to modify a copy of a property's backing store (directly).


See http://msdn.microsof...v=vs.71%29.aspx
MaulingMonkey
MaulingMonkey

I have no problem with properties per se; in fact they're very useful for introducing certain types of logic and semantics. But empty properties are worthless.

They allow you to implement interfaces that contains properties, and switching to properties after the fact introduces a number of breaking changes:
Passing by ref will no longer compile (e.g. F( ref foo.Property );)
Writing to individual member fields/properties will no longer compile (e.g. foo.Property.X = 42;)
Calling struct methods that modify the structure will now modify a temporary copy which is discarded rather than the original! (e.g. foo.Property.IncrementX();)

That last point is sticky and subtle enough that I have no problem with anyone who wants to 'future proof' by preferring default properties. This can also be argued for on a consistency basis. Being able to make only the class itself able to modify a property, but still publicly readable, is also very handy:

public int Count { get; private set; }

(All this said, I'm lazy and don't bother with making fields into properties most of the time. And yes, this does mean I spend more time refactoring. In personal practice, only the middle case bites me in the ass.)
doesnotcompute
doesnotcompute

Consider: in C#, the syntax foo.Field will work to access Field whether Field is a public member or a property. So the best course of action is to begin with public fields, and if you need to refactor to add logic later, drop in a property named Field with the associated logic. No calling code needs to be changed, meaning you only have minor code site updates to make, and everything continues to work swimmingly.


Public fields can be passed with out/ref semantics but a public getter can't. That's why people tend to favor public fields for types like Vector2/3/4 and Matrix in XNA. Also, something like foo.Position.X += 1 (where Position is a property) wouldn't work either. So there are reasons I would favor public fields in XNA, but saying they are syntactically identical to getter methods isn't really true.

EDIT: Ahh I see MaulingMonkey said everything I did

Another thing worth pointing out is that the C# compiler for Xbox 360 doesn't do any inlining of method calls, so there's another reason you may want to favor public fields in some cases.
ApochPiQ
ApochPiQ
I am now more educated on C#'s properties semantics - thanks to all for pointing out my inaccuracy :-)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.