Properties vs. public members

Tuesday 8 March 2005

I've been using FxCop to lint my C# code. It's a very impressive tool. It uses introspection to analyze .NET assemblies and report on all sorts of problems. Like most tools of this sort, some of the suggestions are useful, some are just noise, and some seem contrary to progress.

One of the things it's bothered about is public members in classes. If you write code like this:

// version 1
class MyClass
{
    public string MyString;
}

then FxCop will complain and direct you to this explanation: Do not declare visible instance fields. The guidance directs you to rewrite it like this:

// version 2
class MyClass
{
    private string myString;

    public string MyString
    {
        get { return myString; }
        set { myString = value; }
    }
}

The reason given for all the extra verbiage is to avoid exposing implementation details. But this seems misguided to me. After all, the caller of version 1 writes something like this:

MyClass myobj = new MyClass();
myobj.MyString = "little bunny foo-foo";

while the caller of version 2 writes something like this:

MyClass myobj = new MyClass();
myobj.MyString = "little bunny foo-foo";

That's right: they're exactly the same. So how have I exposed an implementation detail? I could start with version 1, and change it to version 2, and no calling code would have to change at all. Ergo, the implementation is not exposed.

The FxCop documentation takes pains to point out that version 2 is optimized to be as efficient as version 1. But I still have to write and later wade through those extra lines of code, and for what?

Am I missing something because I'm a C# and .NET newbie? In Python, getters and setters are superfluous. Is C# so different?

Comments

[gravatar]
xtian 12:27 AM on 9 Mar 2005

This is something I see all the time, and it makes me feel like I'm taking CRAZY PILLS!

A lot of this seems like B&D programming, where I feel a lot more comfortable with the dynamic type system in Python.

From what I can tell, the only reason to do this is that field accesses can't be virtual. So any inheriting class that wanted to catch gets or sets of a member of the parent class can only do it if the parent class used properties.

Otherwise, the compiler will force them to shadow the parent's field with the new modifier, and any access to the member through a parent-typed reference to a child instance would resolve to the statically determined parent field, rather than the child property.

Even if that's a justification, I've never seen people who make these do-nothing properties make them virtual. Which makes the effort entirely pointless.

The only time I can see that I would even think about doing this is where I was building a library/framework where programmers subclassing the framework classes wouldn't be able to change the library to convert a parent class's field to a virtual property in the event that they needed to catch a field access in a child class. And even then I'd be more likely to curse the .NET developers for not allowing fields to be virtual (and not making things virtual by default).

<pant pant> Sorry for the rant.

[gravatar]
Kevin M. Owen 1:07 AM on 9 Mar 2005

In addition to the points xtian made (and I fully agree that virtual should have been the default), there are some (minor) compatibility issues with changing a field to a property. Though Ned is right that it is still source-compatible, it is not binary compatible. With a property, Ned's example would actually be compiled to:

MyClass.set_MyString("little bunny foo-foo");

[gravatar]
Jim 1:20 AM on 9 Mar 2005

One reason to do this up front is if you want to change the implementation later, and say, myString is no longer implemented internaly as a string, but is derived from some other quantity or object. Then you're hosed and you have to change the interface. If you've exposed a property, you can just re-write the accessor. So, say you've changed the internal to be an enum instead of a string. Your code would become

private MyEnum myStuff;

public string MyString
{
get { return myStuff.ToString() ; }
set { myStuff = Enum.Parse(typeof(MyString), value); }
}

And the caller can still use

thingy.MyString = "Thing1";

(The difference being, that now, the setter will have the possible side effect of throwing an exception if the string you set the property to does not represent an item in the enum...)

So, the primary benefit is the flexibility to go back and change the implementation later and not adversely impact consuming code. And if you're worried about all that typing, I know of a good code generator... :)

Properties also allow you to add side effects to the getters and setters as you go along. For example:

public string Foo
{
get {this.requests++; return myFoo; }
set {this.changes++; myFoo = value; }
}

Also, in subclasses, you can do funky stuff like

public override string Bar
{
get { return base.Bar + ", and much, much more!!!"; }
}

[gravatar]
DominicCronin 4:10 AM on 9 Mar 2005

Jim: a nice argument, but surely you could implement the property later if you need to add extra goo.

[gravatar]
Wild Bill 4:13 AM on 9 Mar 2005

I'd also agree that you should never expose internal class members - keep your privates, private. After all, you may add data validation, etc. And how else can you trap getters and setters ?
So yes - on trivial classes, it does look ridiculous. But as you start to write production code, it does save you ass big style.

I banged on a lot about this in my lotusfear presentation..

http://www.billbuchan.com/web.nsf/htdocs/BBUN693HVL.htm

---* Bill

[gravatar]
Nik Shenoy 10:31 AM on 9 Mar 2005

I wrote a similar entry about this issue in LotusScript. The inheritance argument is a good one; I'm pretty sure LotusScript would get upset if you tried to turn a member variable into a property in a subclass.

The popularity of Java is to blame here. Java programmers that are used to the getter/setter idiom take this baggage with them into other languages. In my opinion, except for inheritance and binary compatibility, it's wasteful to make properties that directly get and set a member variable. I think the language designers could make a few tweaks to make this completely transparent and greatly reduce code clutter.

[gravatar]
Julien Couvreur 11:31 AM on 9 Mar 2005

Another difference between member variable and property: you can only use "ref" on member variables.
See http://www.geocities.com/csharpfaq/properties.html

I personally don't mind having public members for the same reason that you argued. "ref" is not very common anyways...

[gravatar]
Jim 1:18 PM on 9 Mar 2005

Dominic, There's still the issue of subclasses that may be depending upon knowing that a public member variable is of a certain type. If you change the underlying member variable in the superclass, this will potentially break the subclasses.

[gravatar]
xtian 5:23 PM on 9 Mar 2005

But Jim, if you want to change the type of a member, while keeping your interface the same for subclasses, then why wouldn't you change the field to a property when you need to make the change? There's no need to use properties until then - they're merely bloat.

What I'm complaining about is the blanket assertion that public fields are bad in C#, when there's a perfectly good non-interface-breaking migration path from public fields to properties.

(Admittedly, the binary interface would change, as Kevin points out. I've never seen this to be a problem, but I suppose in a very large project where a recompile would take significant time it could be an issue. I would tend not to worry about this time - it's only a computer. They like doing tedious repetitive things!)

Certainly, if you want to be able to lazily initialise members, or log accesses, or make them derive from other members, or any other trickery, properties are great. But if you're not doing anything with them, they are busywork. And that makes me sad.

[gravatar]
Adam Vandenberg 6:08 PM on 9 Mar 2005

Fields and properties are introspected differently, too.

Related, the form builders will show you properties on your control/component, but not fields.

[gravatar]
Damian Cugley 4:12 AM on 10 Mar 2005

Banning public member variables is a hangover from Java, where there is no 'properties' shorthand. In C# I think it comes down to a general feeling that the more you type, the more safe you are. Visual Basic .NET is even more verbose.

If public fields are so wrong, why do you have to go to the trouble of typing an extra keyword every time to control theirt visibility? I miss the C++ convention, where a whole slew of declarations were marked private or public in one go.

So much simpler in SmallTalk, where methods are always public and member variables always private: no need for special keywords at all.

[gravatar]
Damian Cugley 4:22 AM on 10 Mar 2005

Also, FxCop describes itself as checking against 'framework guidelines', which I assume means checking your code as if it were to be a reusable library, which makes sense because it presumably started life as a way to coerce the billions and billions of developers on the Dot-Net libraries in to being vaguely compatible with one another. In this context, the difference in binary calling convention between fields and properties would matter, because you would not have the option of simply recompiling all your callers' code.

[gravatar]
Paul 12:37 AM on 7 Oct 2008

In .NET you can use the members of a specified class to bind a control, such a combo box or a list. Like:

aList.DataSource = myClass;
aList.DisplayMember = "aMemberProperty";
aList.ValueMember = "anotherMemberProperty";

For string seems to work with public member (instead of property), but for int doesn't. This is at least one reason to use properties instead of public members.

Add a comment:

name
email
Ignore this:
not displayed and no spam.
Leave this empty:
www
not searched.
 
Name and either email or www are required.
Don't put anything here:
Leave this empty:
URLs auto-link and some tags are allowed: <a><b><i><p><br><pre>.