25

When I write a class I always expose private fields through a public property like this:

private int _MyField;
public int MyField
{ get{return _MyField; }

When is it ok to just expose a public field like this:

public int MyField;

I am creating a structure called Result and my intention is do this:

public Result(bool result, string message)
{
   Result = result;
   Message = message;
}

public readonly int Result;
public readonly int Message;

What is the best practice? Is it ever ok to do this?

Micah
  • 111,873
  • 86
  • 233
  • 325
  • See also [this question](http://stackoverflow.com/questions/111461/auto-implemented-getters-and-setters-vs-public-fields). – Dimitri C. Mar 10 '11 at 08:56
  • Note that even the [.NET Framework source](https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,19659) uses non-private fields at times. – jrh Jun 06 '17 at 19:47

11 Answers11

32

I only ever expose public fields when they're (static) constants - and even then I'd usually use a property.

By "constant" I mean any readonly, immutable value, not just one which may be expressed as a "const" in C#.

Even readonly instance variables (like Result and Message) should be encapsulated in a property in my view.

See this article for more details.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • skeet although theoretically you might be right. All this over-encapsulating results in applications still be as slow as 10 years ago, while the hardware specs grew orders of magnitude. – Toad Oct 14 '10 at 11:52
  • 13
    @Toad: No, it doesn't... because the JIT compiler inlines trivial properties anyway. – Jon Skeet Oct 14 '10 at 11:54
17

What is the best practice for using public fields?

“Don’t.” See also: Should protected attributes always be banned? which concerns protected fields but what is said there is even more true for public ones.

Community
  • 1
  • 1
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
9

Use properties. It's easy now that C# has Automatic Properties!

Dave Markle
  • 95,573
  • 20
  • 147
  • 170
4

The best practice is to use properties for several reasons. First, it decouples the API from the underlying data structure. Second, anything built into the framework that binds to objects does to to properties, not fields.

I'm sure there are more reasons, but those two always seem to be enough for me.

Greg Hurlman
  • 17,666
  • 6
  • 54
  • 86
3

I think best practice is not to do it. Unless you have some extreme performance need where you must access the field directly don't do it.

Here is a good article about it:

http://csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
2

I recommend using something similar to this:

public class Result{  
    public bool Result {  get; protected set; }
    public string Message {  get; protected set; }

    public Result(bool result, string message) {
        Result = result;
        Message = message;
    }
}

This way, you don't need to declare member variables, let the compiler do the work for you! The code is very clean and short, and refactoring is a breeze.

Mark Carpenter
  • 17,445
  • 22
  • 96
  • 149
2

In C-Style languages (like C#) you should expose fields through properties. This also pertains to VB.NET and other .NET languages as well as they share the same underlying engine. The main reason to do this is that

Public MyField as Integer DOES NOT EQUAL Public Property MyField as Integer, They don't have the same behavior in all situation under .NET.

However you will probably see a lot of people continuing to make public Fields. Some of this is due to how VB6 handles COM. In VB6 Public MyField as Integer is equivalent to Public Property MyField as Integer. Because when both are translated into a COM typelib they both are implemented in the same way.

This resulted in a lot of odd restrictions in VB6 over what could be a public field. Restrictions that are not in .NET and a lot of other Object Oriented languages. These restrictions are caught at compile time so prevent a programmer from shooting themselves in the foot so to speak. If your class was private in VB6 some of these restriction, but not all, were eased. The general rule was that you could only expose classes and data types as public fields.

The legacy of VB6 means there are lot of programmers that are not aware that there is a difference in .NET.

Because .NET doesn't help us in this regard then you need to take the tradition step of making sure all fields are exposed through properties. Again because in .NET a field is not the same as a Property.

This article (pointed out by others) explains the .NET side of it.

RS Conley
  • 7,196
  • 1
  • 20
  • 37
  • 1
    FWIW this is the only answer that makes a good argument (too me as a former VB6-er) for the "best practice". I like to know why, not just what. + 1 Thanks – Booji Boy Dec 19 '08 at 13:52
  • Based on what I read, I believe if you restrict yourself to classes and data types then fields will be equivalent to properties in behavior. No structs, no arrays. – RS Conley Dec 19 '08 at 14:07
1

What is the difference between a Field and a Property in C#?

Community
  • 1
  • 1
Joe Phillips
  • 49,743
  • 32
  • 103
  • 159
1

I would like to answer on your aproach of readonly.

Readonly isn't a way to have only a get accessor on a public field. I mainly use readonly on private field where my private field can only be set from constructor. So to be understand a readonly field can ONLY be set in a contructor and then you can only acess it.

The best practices is to always use Properties to access your fields after constructor. so in case you would have to access your properties from inside your class I would put :

private readonly int result;
private readonly int message;

public Result(bool result, string message)
{
   this.result = result;
   this.message = message;
}

public int Result
{
   get{ return result; }
   private set { result = value; }
}

public int Message
{
   get{ return message; }
   private set { message = value; }
}

That way you can only read Result and Message and can still write to it from inside the class.

In case you use inheritance, you could put the set protected if needed.

EDIT: After reading the code I made based on what was given in the question there is some bug where the Class name Result will probably throw an error with the property Result and also the fact the we are receiving a bool as result and a string as message in constructor but trying to send them in a int this will definatly don't work. But for what it's worth here is something mor logic :

private readonly bool result;
private readonly string message;

public Answer(bool result, string message)
{
   this.result = result;
   this.message = message;
}

public bool Result
{
   get{ return result; }
   private set { result = value; }
}

public string Message
{
   get{ return message; }
   private set { message = value; }
}
jpsimard-nyx
  • 8,587
  • 6
  • 32
  • 48
  • Good explanation however, you shouldn't have a Private setter on the properties since they can only be set at runtime. – Micah Dec 19 '08 at 14:19
0

In general, if an type is going to be used as a data holder, it should either be:

  1. A mutable struct with exposed fields, if each of the fields will behave as a value from the standpoint of the type, and any arbitrary combination of field values will "make sense". Note that the fields holding references to mutable class types may qualify if the purpose of the fields is to hold the identity of the objects in question, rather than the contents. Structs with mutable fields got a bad reputation as a result of silly C# compilers that would interpret `SomeThing.SomeStruct.SomeField = whatever` as `tempStruct = SomeThing.SomeStruct; tempStruct.SomeField = whatever` without issuing a diagnostic, but there's no reason for programmers today to worry about such what ancient compilers would do.
  2. An immutable class or struct with non-public fields, for situations where the above do not apply, and where having to regenerate an entire data item to change one aspect thereof would not be overly bothersome.
  3. A mutable class, if references to it will not be persisted outside the entity which creates it (such references should generally never be exposed to outside code). Note that the other two options, when workable, should be vastly preferred, since a collection which uses a mutable class type as data holder (as opposed to a collection which simply stores the identities of objects but don't care what those objects represent) will often have to make a defensive copy of any object which is stored in the collection, and then make an additional defensive copy every time the object is read. Structs, whether mutable or "immutable", must be copied whenever they are stored or read back from a collection, but such copies are cheaper, for any size struct, than the defensive copies that would be required if using a mutable class.

If there is no practical alternative to using a mutable class, the question of whether to expose public fields depends upon whether there's any foreseeable need for any version of the class to include validation logic in a property setter, and also whether the type of a member will be a value type or class type. If Bounds is a public field of type Rectangle, an expression like SomeClass.Bounds.Width can access the Width of the rectangle without having to access any other members. By contrast, if Bounds were a property--even a mutable one--that expression would have to copy all four members of Bounds to a temporary structure, and then access the Width field of that.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

The answer I give is that Properties are more Refactor friendly.

If you have an assembly with read-only fields, then change them to properties. If you have another assembly that I accessing the fields (now properties), they wont work without a compile. Fields and properties are not the same as far as the compiler is concerned.

Back to refactoring, say you started with a property. Now you need to change where the data is coming from (you will access it from another class). If you were dealing with fields you have some hard decisions to make on how to make that happen. Properties are much more forgiving -- because you can hide logic in them.

Chris Brandsma
  • 11,666
  • 5
  • 47
  • 58