What's the point of an auto property?

2k views Asked by At

This might sound naive, but...

class Widget
{
    public int Foo { get; set; }
}

That's cool, and saves some boilerplate against using a backing field, but at that point, isn't it equivalent to simply:

class Widget
{
    public int Foo;
}

Seems like it's little more than a public field, though I suppose it looks different under the hood. From a design point, though, what's the advantage of using a property if it doesn't aid encapsulation?

6

There are 6 answers

4
Andrew Hare On BEST ANSWER

Because it gives you the potential to add encapsulated logic later without changing the metadata of the class.

Using properties is considered a best practice - automatically implemented properties were designed to take away the tediousness of writing properties to encourage developers to adhere to this best practice

0
BinaryTox1n On
  1. Some sort of standards any programmer may be required to follow for whatever reason
  2. Reflection works differently on properties than on variables
  3. You can't databind against a variable
  4. You have to rebuild all code that used the variable if you ever decide to change it to a property
1
Eric Lippert On

In addition to the other good answers posted so far:

  • it is easy to quickly create a private-setter-public-getter property, which is an arguably better practice than a public readonly field for making an immutable data type.
1
Qyuubi On

From msdn:

Properties combine aspects of both fields and methods. To the user of an object, a property appears to be a field, accessing the property requires the same syntax.

You can do something like this:

public class Date
{
private int month = 7;  // Backing store

public int Month
{
    get
    {
        return month;
    }
    set
    {
        if ((value > 0) && (value < 13))
        {
            month = value;
        }
    }
}
}

Simply put properties are a lot more versatile.

0
Steve On
  1. properties allow you to add encapsulation to your class
  2. properties allow your access to be polymorphic (inheritors can modify access if the property is virtual) if you so choose.
  3. auto-properties are nice when you're dealing with simple get/set operations. if you do more complicated operations inside your get / set, then you can't use the auto-property.

also, reflection doesn't work differently on properties than it does on variables though, you're working with a MemberInfo (FieldInfo, PropertyInfo, or MethodInfo whichever way you choose).

0
paraJdox1 On
  • We use auto-properties if our getters and/or setters doesn't have any custom logic.

  • Auto-properties also "automatically" defines the "backing fields" for us.

This is what is happening "under the hood" when we implement an Auto-property:

Your class:

public class YourClass {
    public int Foo { get; set; }
}

The IL Code:

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit YourClass
    extends [System.Private.CoreLib]System.Object
{
    // Fields
    .field private int32 '<Foo>k__BackingField'  //this is the backing field for your property
    .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )

    // Methods
    .method public hidebysig specialname 
        instance int32 get_Foo () cil managed //this is the GETTER of your property
    {
        .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x2050
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldfld int32 YourClass::'<Foo>k__BackingField'
        IL_0006: ret
    } // end of method YourClass::get_Foo

    .method public hidebysig specialname 
        instance void set_Foo (
            int32 'value'
        ) cil managed //this is the SETTER of your property
    {
        .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x2058
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldarg.1
        IL_0002: stfld int32 YourClass::'<Foo>k__BackingField'
        IL_0007: ret
    } // end of method YourClass::set_Foo

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2061
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
        IL_0006: ret
    } // end of method YourClass::.ctor

    // Properties
    .property instance int32 Foo()
    {
        .get instance int32 YourClass::get_Foo()
        .set instance void YourClass::set_Foo(int32)
    }

} // end of class YourClass


You can check it here too.