22

I read somewhere that having public properties is preferable to having public members in a class.

  1. Is this only because of abstaraction and modularity? Are there any other over-riding reasons?

  2. The property accesses are conerted into function calls by the compiler. For properties without a backup store (e.g. public string UserName { get; set; }), what would be the performance overhead compared to a direct member access? (I know it shouldn't usually make a difference but in some of my code, properties are accessed millions of times.)

Edit1: I ran some test code over integer members and Properties and the public members were about 3-4 times as fast as Properties. (~57 ms. vs ~206 ms. in Debug and 57 vs. 97 in Release was the most common run value). For 10 million reads and writes, both are small enough not to justify changing anything.

Code:

    class TestTime1
{
    public TestTime1() { }
    public int id=0;
}
class TestTime2
{
    public TestTime2() { }
    [DefaultValue(0)]
    public int ID { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        try
        {
            TestTime1 time1 = new TestTime1();
            TestTime2 time2 = new TestTime2();
            Stopwatch watch1 = new Stopwatch();
            Stopwatch watch2 = new Stopwatch();
            watch2.Start();
            for (int i = 0; i < 10000000; i++)
            {
                time2.ID = i;
                i = time2.ID;
            }
            watch2.Stop();
            watch1.Start();
            for (int i = 0; i < 10000000; i++)
            {
                time1.id = i;
                i = time1.id;
            }
            watch1.Stop();
            Console.WriteLine("Time for 1 and 2 : {0},{1}",watch1.ElapsedMilliseconds,watch2.ElapsedMilliseconds);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.In.ReadLine();
    }
}
apoorv020
  • 5,420
  • 11
  • 40
  • 63
  • Serialization and DataBinding are the reason i can think of – LiFo Jul 16 '10 at 13:03
  • 5
    The factor difference for the unoptimized debug build is irrelevant. You're not shipping the debug build to customers. Also, I note that in your test you are measuring *jit time of the property* as well as *access time*. If you're interested in the *amortized* cost of a jitted property including the startup time of jitting it, that's one thing. But if what you're interested in is the *per usage* cost then *don't conflate the jit cost with the per usage cost* as you are doing here. And regardless of whether your measurement technique is good: optimize *the slowest thing*. I doubt this is it. – Eric Lippert Jul 16 '10 at 15:19
  • possible duplicate of [Why are public fields faster than properties?](http://stackoverflow.com/questions/632831/why-are-public-fields-faster-than-properties) – nawfal Jun 03 '13 at 18:50

9 Answers9

21

Running the test 20 times in a row, ensuring that JIT optimization is enabled in the Release build:

Time for 1 and 2 : 47,66
Time for 1 and 2 : 37,42
Time for 1 and 2 : 25,36
Time for 1 and 2 : 25,25
Time for 1 and 2 : 27,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 26,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25

Yes, the JITter is that good at inlining property accessors. Perf is a non-issue and should never be considered.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Hmm... did the testing in debug instead of release. My bad! – apoorv020 Jul 16 '10 at 13:56
  • In release, there's still a 80% overhead on my machine. My machine is 32-bit, I have seen some strange performance differences between 32-bit and 64-bit. – apoorv020 Jul 16 '10 at 14:00
  • 3
    Mine is 32-bit as well, I assume we use the same JITter. Tools + Options, Debugging, General, uncheck "Suppress JIT optimization on module load". – Hans Passant Jul 16 '10 at 14:11
18

Don't worry at all about the performance overhead. It is so minor that you should not consider weakening the encapsulation of the class; it would be premature optimization of the worst sort.

Steven Sudit
  • 19,391
  • 1
  • 51
  • 53
9

Is this only because of abstaraction and modularity? Are there any other over-riding reasons?

Not that I know of; these reasons are by themselves compelling enough. But maybe someone else will jump in on this.

The property accesses are conerted into function calls by the compiler. For properties without a backup store (e.g. public string UserName { get; set; }), what would be the performance overhead compared to a direct member access? (I know it shouldn't usually make a difference but in some of my code, properties are accessed millions of times.)

In the resulting Intermediate Language, a property access is translated to a method call. However, as the word says, this is only an Intermediate Language: it gets compiled Just-In-Time down to something else. This translation step also involves optimizations like inlining of trivial methods, such as simple property accessors.

I would expect (but you'd need to test to make sure) that the JITter takes care of such accessors, so there should be no performance difference.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • 1
    Here's one reason: .NET standards dictate that you must not expose a field as public, with very few exceptions. As for inlining, see my comment to Adam. – Steven Sudit Jul 16 '10 at 12:42
  • 10
    The standards dictate this for a reason, and I think it's that reason that we're looking for, not "because Microsoft says so" :) – Thomas Jul 16 '10 at 12:49
  • I would emphasize (eg boldify) the inlinging, as AFAIK that's the case with all properties on both Mono and the CLR. – Dykam Jul 16 '10 at 13:35
  • @Thomas: Yes, absolutely! I don't mean to suggest that this standard is arbitrary or counterproductive. I'm just saying that the very fact that it's a standard is itself a good reason, all things being (more or less) equal, to do it that way. Since performance considerations are inconsequential, I think that fuzzy ceteris paribus criterion is satisfied. :-) – Steven Sudit Jul 16 '10 at 13:40
  • @Dykam: I wouldn't, both because the speed difference is not significant compared to the loss of encapsulation, and because inlining is limited to cases where the caller is in the same assembly. – Steven Sudit Jul 16 '10 at 13:45
  • 2
    Here's a more authoritative answer (with links) on the issue of inlining: http://stackoverflow.com/questions/646779/does-c-inline-properties/646780#646780 – Steven Sudit Jul 16 '10 at 13:49
4

It is mostly for purposes of abstraction (you can later add validation without breaking existing code, or requiring recompilation).

Even when using auto-properties, there is still a backing field generated by the compiler, and will perform as such.

Rowland Shaw
  • 37,700
  • 14
  • 97
  • 166
3

Make sure you're running with Ctrl-F5 instead of F5; otherwise the debugger will still attach and some optimizations may not work the same, even in Release mode. At least that's the case on my machine: F5 gives similar results to what you posted, whereas Ctrl-F5 gives equal results.

Dax Fohl
  • 10,654
  • 6
  • 46
  • 90
1

1) Its for encapsulation principles, but other .NET features use properties such as data binding.

2) I'm not sure I agree with that, I've always heard that if the property is a straight get/set its just as fast as a standard field access - the compiler does this for you.

Update: seems to be a bit of both, compiles to method call but JIT-optimized away. Either way, this sort of performance concern is not going to have a meaningful impact on your code. However, note that the guidance around implementing properties is to make them as light-weight as possible, they are not expected by callers to be expensive.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • There are more details to this. I believe it can only inline the call when the caller and the property are defined in the same assembly, for example. But, really, it doesn't matter. The call overhead is nothing in comparison to what you gain from being able to replace an underlying field with as much logic as you need. – Steven Sudit Jul 16 '10 at 12:41
  • Strange, that's a rather odd detail for not inlining - disappointing in a way lol. As mentioned, the performance detrement, either compiled away or not, is negligible – Adam Houldsworth Jul 16 '10 at 12:49
  • Agreed regarding performance irrelevancy, but I think there's some sense to the limitation. When generating CIL code for the property call, the compiler needs to have access to the implementation so that it can confirm that there's just assignment to a backing variable and so that it can identify that variable. In other words, this optimization is part of the original compilation, not the final JIT one. – Steven Sudit Jul 16 '10 at 13:43
  • Ah yea, that does make sense. – Adam Houldsworth Jul 16 '10 at 13:46
  • At the risk of repeating myself, here's a link to a more authoritative answer: http://stackoverflow.com/questions/646779/does-c-inline-properties/646780#646780 – Steven Sudit Jul 16 '10 at 13:50
0

If you want a specific example of something that properties are needed for that you can't do with regular member variables, think about inheritance: if a class uses a public member, derivations to this class cannot implement validation or other getter/setter behavior. They're stuck with the variable as it is, and if they want to do something different, they have to 1) ignore the existing member variable and create a new property, 2) add a new property, and 3) override every method that called or relied on the member variable to use the property instead. Not only is this unnecessarily more work, if the person writing the derived class doesn't have access to the source it may be nearly impossible.

If the base class uses properties instead of member variables, it's just a question of adding the validation or other behavior to the get/set function, and you're done.

user2310967
  • 285
  • 2
  • 5
0

After I posted this post, I realized that it's basically for hiding the inner workings of you object.

Community
  • 1
  • 1
JSprang
  • 12,481
  • 7
  • 30
  • 32
0

I've asked the same question before.

I'm guessing you're using VS2008, are using a 64-bit OS and have compilation set to "Any CPU"? If so, properties don't get inlined by the x64 JIT compiler. They do on 32-bit, making them identical in performance to public fields.

Community
  • 1
  • 1
JulianR
  • 16,213
  • 5
  • 55
  • 85