Search code examples
c#propertiescil

Do C# properties always have backup fields "behind the scene"?


I know that when we use properties in C#, the compiler always generate getters and setters for them in CIL (i.e., get_PropertyName and set_PropertyName), for example, consider the following piece of code:

    class Program
    {
        class Test
        {
            public string Name { get; set; }
        }
        static void Main(string[] args)
        {
            //Here I'm using reflection to inspect methods of Test class
            Type type = typeof(Test);
            foreach (var item in type.GetMethods())
            {
                Console.WriteLine(item.Name);
            }
        }
    } 

This program will produce output with the methods of Test, among which there will be get_Name and set_Name - the getter and setters I was talking about. From my understanding then, if getters and setter are created "behind the scenes" then there should be a backing field created as well from which/to which the getters and setter get/set values. So, from the previous example, I can use reflection to inspect fields for Test class, like that:

    static void Main(string[] args)
    {
        Type type = typeof(Test);
        foreach (var item in type.GetFields())
        {
            Console.WriteLine(item.Name);
        }
    } 

The ouput of this program is empty, I assume this is because the backing field that was created has private access, so we cannot see it. But since I don't know how to check it, can you please let me know if a backing field always gets created (even if we have a simple property with only get; and set;) ?


Solution

  • If you mean simple properties like:

    {get;set;}
    

    or:

    {get;}
    

    then yes, there is a field; add BindingFlags.NonPublic | BindingFlags.Instance to your GetFields() call and you'll see it:

    foreach (var item in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
    {
        Console.WriteLine(item.Name);
    }
    

    It usually has an unpronouncable name involving <> - yours is <Name>k__BackingField on my machine - but: this name is a compiler feature (although a lot of serialization etc libraries make use of it, so it is unlikely to change).

    But: no, properties don't by themselves always involve fields; for example:

    public int Value => 42; // no field
    

    or

    public int Name { get { return obj.Name; } set { obj.Name = value; } }