3

if i have a private property in a class, i'm wondering what technically the difference is between the following three scenarios (memory usage, usability, best practice, etc):

class testClass
{
     private string myString1 = "hello";

     private string myString2 { get { return "hello"; } }

     private string myString3() { return "hello"; }
}

apart from obviously being able to set the value in myString1 and not in myString2 or myString3, i'm wondering more about how these differ in terms of efficiency?

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
benpage
  • 4,418
  • 3
  • 41
  • 39

6 Answers6

8

I try to follow these rules where possible:

  • Fields should be kept private
  • Properties should be used to expose data
  • Methods should be used to perform an action

There are obviously going to be some situations where every last drop of performance is important, but in general I would attempt to follow best-practice until profiling tells you that optimisation is needed.

There's a good article here: Why Properties Matter

LukeH
  • 263,068
  • 57
  • 365
  • 409
5

I personally prefer properties for things without side effects and explicit getter if something is calculate on the fly. Eg:

class User {
    private string username;

    public string Username {
        get { return username; }
        set { username = value; }
    }

    public Post GetLatestPost() {
        // query the database or whatever you do here.
    }
}

And a lot of the APIs I've seen seem to do it similar. Hope that helps.

Armin Ronacher
  • 31,998
  • 13
  • 65
  • 69
2

All these methods are very different in terms of what they get compiled to, though very much similar in terms of use. I'll try to summarise the differences in brief:

  1. This is a simple private instance variable. It's easily going to be the most efficient when referencing.

  2. This is a read-only property (i.e. a get but no set accessor).

  3. This is a normal parameterless function. I suspect you're just offering these examples purely as a point of comparison, and realise that such a function is totally useless (as are private properties, in almost all cases). The layout (i.e. everything on one line) is also rather horrible.

Methods 2 and 3 are going to be equally inefficient compared to 1 in that they both involve the overhead of function calls. I don't know by memory the CIL code that they all compile to (maybe someone else can produce that), but they certainly involve a few more instructions, whereas referencing myString1 ought to only require a single instruction in CIL.

Not sure I can make a very useful comment on best practice without knowing more about the context, but method 2 (i.e. a private property) is generally seen as quite useless. The third method should never be used in my opinion (it's begging to be turned into a property). I think what you really want is just a plain old private variable, so definitely go for the first declaration. Public values should always be accessed as properties rather than variables in classes (i.e. a private/protected backing variable to a property), but that is slightly unrelated to your question. (You could find plenty of resources discussing the matter in a quick search anyway.) Finally, note that if your "property" is going to be read-only (i.e. not modified at any point), you really want to use a constant, i.e. private const string myString1 = "hello";.

Hope that helps clarify things a bit.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
  • I would be shocked to learn the C# compiler could not detect such a basic optimization. Surely they all compile to the same thing? – LegendLength Mar 24 '09 at 02:59
  • The C# compiler doesn't optmize it, but the JIT compiler will however. There is a difference between the x86 JIT's ability and the x64 JIT's ability to do this, mainly that the x86 JIT is much better at it. The x64 JIT doesn't optmize method calls away for properties for exaple. – JulianR Mar 24 '09 at 12:16
  • Even if the JIT does optimise 2. and 3. in the end, it's best not to rely on it for the sake of good practice and readability. – Noldorin Mar 24 '09 at 12:51
0

Thats a good question:

You have this alternatives:

private string myString = "hi!";   //Private Field

public string MyString             //Property created to the private field
{
  get {return myString;}
}

public string myString {get; private set;}   //VS2008 automatic properties

public string getMyString()                  //Method Way
{
   return myString;
}

As you can see the idea is the same, not to violate the encapsulation principle. Use the one you feel more comfortable with, all of them achieves the goal, but I recommend property way or the VIsual Studio 2008 automatic Property.

Is more concise and clear to see than the methods.

Hope this helps!

Regards!!

MRFerocius
  • 5,509
  • 7
  • 39
  • 47
0

As far as best practices go,

class testClass
{
   private string _myString;

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

   public testClass()
   {
      myString = "Hello";  // Initial value.
   }
}

Is generally recommended as it implements encapsulation (hiding internal state so that all manipulations pass through the methods/interface). Of course, the setters and getters are often methods themselves.

In C# 3.0, you can replace the above with:

class testClass 
{    
  public string myString { get; set; }

  public testClass()
  {
      ...
  }
}

As far as efficiency goes, you really should not be thinking about your design in terms of whether direct access to a variable is more efficient than a property. The difference is so small (if any) and the best practices guidelines so clear that you are just going astray worrying about efficiency.

Mark Brittingham
  • 28,545
  • 12
  • 80
  • 110
-1

All of the above discussions about design, style etc are valid. But the question is about performance. Easy enough to test. Wrapped some timers around each of the invokations, repeated to int32.Max. On my machine the below code shows that the myString1 is much faster. (Note that I had to change the class definition to make the members public):

    private void button2_Click(object sender, EventArgs e)
    {
        //performance test
        testClass t = new testClass();
        System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch();
        sw1.Start();
        for (int i = 0; i < int.MaxValue; i++)
        {
            string result = t.myString1;
        }
        sw1.Stop();

        System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch();
        sw2.Start();
        for (int i = 0; i < int.MaxValue; i++)
        {
            string result = t.myString2;
        }
        sw2.Stop();

        System.Diagnostics.Stopwatch sw3 = new System.Diagnostics.Stopwatch();
        sw3.Start();
        for (int i = 0; i < int.MaxValue; i++)
        {
            string result = t.myString3();
        }
        sw3.Stop();
        MessageBox.Show(string.Format("Direct: {0}, Getter: {1}, Method: {2}"
            , sw1.ElapsedMilliseconds.ToString()
            , sw2.ElapsedMilliseconds.ToString()
            , sw3.ElapsedMilliseconds.ToString()));
    }


class testClass 
{ 
    public string myString1 = "hello";
    public string myString2 { get { return "hello"; } }
    public string myString3() { return "hello"; } 
}
Ilya Tchivilev
  • 822
  • 7
  • 10
  • For being "easy to test," I think you blew it. The first loop is probably completely optimized out by the compiler because it's doing nothing, but the second and third loop are function calls and can't be optimized out as easily. Try adding more processing in the loops and check again. – mqp Mar 23 '09 at 23:51
  • You might be right, but I added an integer to which the length of the string is being added, and the results are still pretty damning - the field is still faster. – Ilya Tchivilev Mar 24 '09 at 00:35
  • Well are you going to share the speed results? – Caleb Vear Mar 24 '09 at 00:36
  • 1
    Run the code :), see for yourself. My results were: Direct: 4967, Getter: 7350, Method: 7164. Your mileage may vary, but I imagine the ratios will be similar - ie direct access is significantly faster. – Ilya Tchivilev Mar 24 '09 at 04:47