views:

495

answers:

11

I'm working in C# 2.0, but this would apply to most object oriented languages. When I create classes with public properties that wrap private fields, I switch back & forth between whether I should use the property or field internally. Of course C# 3.0 makes this easier with auto-properties, but it could still apply.

Does it matter?

public class Person
{
    private string _name = "";

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public Person(string name)
    {
        _name = name; //should I use the property or field here?
    }
}
+2  A: 

Mostly it's like a code preference, but I' prefer to use public properties or ever private properties, you could simply add some logic to property without any changes in caller code. Also in 3.5 .NET you have useful code sugar as autoproperty.

pocheptsov
+2  A: 

I would recommend using the property, You never know when you might being doing something inside your property ie. lazy loading, conversion, formatting, calculation, etc. that would introduce a bug if you used the private member...

J.13.L
A: 

Normally I use the public properties with some exceptions where I may want to avoid any extra code written in the property accessor. With automatic properties in C#3.0 I rarely create backing fields by hand; typically only when the default value of the automatic backing field is not appropriate for my property.

tvanfosson
A: 

At least in Java, there is NO way you would use public fields because the good old javabeans conventions, that everybody seems to use. I guess C# has properties as first language constructs. I would go for that

Marcelo Morales
Yes it does, a big benefit of C#.
Randolpho
What are ya talkin aboot for those of us that don't know these javabeaner thingies?
Joe Philllips
You should not follow conventions just because "everybody seems to use them," especially if you can't justify it yourself. The convention does not imply or prove that it is a good idea. Question it! :)
JoshJordan
A: 

You should use "Name" (property), because if you want some checks for this value, you can place it into setter of "Name" property and then will be used for constructor and for lately setting value too.

TcKs
+1  A: 

Use the Property. Or better yet, if you're using C# 3.0 or above use Automatic Properties like so:

public class Person
{
    public string Name { get; set; }

    public Person(string name)
    {
        Name = name; //should I use the property or field here?
    }
}

If you use the property now you'll be ready when you modify your code to use Automatic Properties.

CLaRGe
+11  A: 

Basically, because you can implement your validation and other logic in the property, you should access through the property unless you have a specific reason not to.

It helps with consistency within your object, because that way you know that the values of your private fields have gone through whatever rigors you choose to put in your accessor or setter methods.

On the other hand, the constructor can possibly be an exception to this, because you might want to set initial values.

But in general, I'd say access through the property.

EDIT

A (trivial/contrived) example

public class Person
{
    private string _name = "";
    private List<String> oldnames = new ArrayList();

    public string Name
    {
        get { return _name; }
        set 
        {
           oldnames.Add(_name);
           _name = value; 
        }
    }

    public Person(string name)
    {
        _name = name; //should I use the property or field here?
    }
}

So in this case, you would want the constructor to skip the property but if you EVER use the field again you'll be causing a bug in your code because you're skipping the 'name archiving'. The reason to put validation in your property is so that you don't need to duplicate the validation code in every place that you access the field, so you shouldn't skip it even in private methods.

I think I should point out that Java and C# are different languages. C# has properties, Java does not.
epochwolf
How can I edit my answer to incorporate this feedback?
Oh, I see, yeah for some reason I thought the question was related to Java.
It doesn't matter. The exact same argument applies to Bean-style getters and setters as well.
Jörg W Mittag
It may not really matter but it still bugs me. :)
epochwolf
Actually, properties in C# are purely a syntactic construct. The compiler turns them into Java-style getter and setter methods anyway. A property `P` of type `T` gets compiled into `T get_P` and `void set_P(value T)`. See §10.2.7.1 of the C# 2.0 spec.
Jörg W Mittag
A: 

It depends. Sometimes, you will write getters/setters that do important pre-processing for any realistic interaction with the field. For example, if a string field has a constraint that it must always be lowercase, then at least one of your getter/setter methods must make a call to .ToLower() or .ToLowerInvariant(), and in your class code, you probably want to use this to make sure that the constraint is enforced.

However, there will also be times when you need to circumvent that preprocessing logic. In fact, I have seen times when developers inadvertently create infinite loops by using the public property rather than the private field (can't think of an example off the top of my head, sorry).

Linq To SQL generated classes are a good example, I think, because they show how much logic can exist in a Property. Try writing some extension methods and you'll begin to understand the difference.

I think the bottom line is that it depends on what kind of logic you are using at any given point in the class, and what kind of preprocessing exists in the getters/setters. If you are ever unsure or it seems like it doesn't matter, it is probably better to use the getters/setters/public Property so that you write more maintainable code that will follow constraints added later.

JoshJordan
+1  A: 

Essentially the same question was asked here. There were some good responses there.

itsmatt
+1  A: 

There can be a situation when you'll have to access the field internally. For example, when you only offer publicly the read-only access to a property and do not the value to be allowed to change after an object is instantiated.

public class MyClass
{
    private string _MyProperty;

    public MyProperty { get { return _MyProperty; } }

    public MyClass ()
    {
        _MyProperty = SomeVeryComplexPropertyInitializationLogic ();
    }
}
User
+1  A: 

If you use the field name, you don't get the encapsulation. Encapsulation applies not only between classes, but within a class.

If at some future point, you redefine the field but leave the the accessor/setter function's signatures the same, not only will external classes that use your class not break, but internal routines in your own class also won't break.

Take for example this code, loosely based on code that shows up in the Apache Wicket framework (though the framework doesn't suffer this problem; I'm just using it illustrate):

Let's say this were the original class:

class RadioChoice {
  private String prefix;

  RadioChoice( String prefix ) {
    this.prefix = prefix ;

  setPrefix( String prefix )  {
    this.prefix = prefix ;
   }
}

Here we can already see a problem: the same operation this.prefix = prefix happens in tow places. It's meant to do exactly the same thing, but since it happens in two places, that "same thing" can diverge into two different things. (Compare this to database normalization, a practice designed to prevent exactly that.)

Now, Apache Wicket has a concept of recording changes to how it renders web pages, so that those changes can be undone. It does this by storing a list of "undo" object. A RadioChoice's prefix is one of those things that can be undone, and so the 'prefix' setter must record the change:

class RadioChoice {
  private String prefix;

  RadioChoice( String prefix ) {
    this.prefix = prefix ;

  setPrefix( String prefix )  {
    // save the old prefix
    this.getPage().addChange( new PrefixChange( this.prefix ) );
    // set the new one
    this.prefix = prefix ;
   }
}

Now look what happens: because the constructor set the prefix directly, no change is saved by the ctor. Had we used the setter, the ctor would automatically "do the right thing" after a refactoring. Instead, we have to refactor both the setter and the ctor.

Of course, our code is still less than optimal, in reality it should be this:

  setPrefix( String prefix )  {
    // save the old prefix
    this.getPage().addChange( new PrefixChange( this.getPrefix() ) );
    // set the new one
    this.prefix = prefix ;
   }
}


Scott Meyers had a series of articles on this, where he advocated that (in C++, which has free functions) a class expose only primitive functions (primitive functions: functions not possible except by the class iteslf) and that all functions that could be composed out of primitive functions be made free functions. This makes for a leaner interface, more stable interface.

In that same vein, to the extent that you can treat functions in the class as dependent only on its primitive interface, the more flexibility you have; in particular, those functions are candidate to be moved out of the class. More generally, using setters and getters insulates you from changes.

tpdi