75

I know that I can use the verbose syntax for properties:

private string _postalCode;

public string PostalCode
{
    get { return _postalCode; }
    set { _postalCode = value; }
}

Or I can use auto-implemented properties.

public string PostalCode { get; set; }

Can I somehow access the backing field that is behind the auto-implemented property? (In this example that would be _postalCode).


Edit: My question is not about design, but rather about, let's say, theoretical ability to do so.

Andrey Rubshtein
  • 20,795
  • 11
  • 69
  • 104
  • 9
    being curious!! why do you want that? – Azodious Jan 11 '12 at 09:42
  • 4
    Programming to the implementation is dangerous. – Eranga Jan 11 '12 at 09:44
  • You can access it with private reflection, but that's a bad idea. – CodesInChaos Jan 11 '12 at 09:51
  • 1
    You got the official reference in answers below. but lets say somehow you're alllowed to access `_postalCode` and later they changed it to `__postalCode`. erk!!! running code breaks. – Azodious Jan 11 '12 at 09:52
  • @Andrey: you can use the `private` modifier to limit access to one of the accessors (usually, `set` would be the private one in that case). But since you already opted for the "lazier" auto-implmented version, I see no possible reason to want to access the backing field. – vgru Jan 11 '12 at 09:54
  • @Andrey: CSC or CLR creators. MS people. – Azodious Jan 11 '12 at 09:58
  • @Andrey: Azodious was talking about using reflection to access BCL classes' private fields and meddle with them. But if this is your own class, then it's nonsense. Accessing the field directly or through the auto-implemented property accessors has **no difference and no benefit**. But you are complicating this. unnecessarily. Not to mention that compiler will most probably inline every call. – vgru Jan 11 '12 at 10:01
  • @Andrey: done, I've added an answer below. – vgru Jan 11 '12 at 10:41
  • @Groo: Credit goes to 'CoddeInChaos' for private reflection; not to me BTW. – Azodious Jan 11 '12 at 10:44
  • A good case for this would be if you are writing your own ORM and need to set properties without calling the setter logic. – Brain2000 Apr 08 '21 at 13:22

8 Answers8

63

I don't know about you, but I've written code in projects in other companies, and now I want to know how I did something! So it's usually quicker to do a web search for the answer, and it brought me here.

However, my reasons are different. I'm unit testing, and don't care what purists have to say, but as part of a setup for a unit test, I'm trying to invoke a certain state for a given object. But that state should be controlled internally. I don't want some other developer accidentally messing with the state, which could have far reaching effects upon the system. So it must be privately set! Yet how do you unit test something like that without invoking behaviours that (hopefully) will never happen? In such scenarios, I believe that using reflection with unit testing is useful.

The alternative is to expose things we don't want exposed, so we can unit test them! Yes, I've seen this in real life environments, and just thinking about it still makes me shake my head.

So, I'm hoping that the code below might be useful.

There are two methods here just for separation of concerns, really, and also to aid in readability. Reflection is head-spinning stuff for most developers, who in my experience either shy away from it, or avoid it like the plague!

private string _getBackingFieldName(string propertyName)
{
    return string.Format("<{0}>k__BackingField", propertyName);
}

private FieldInfo _getBackingField(object obj, string propertyName)
{
    return obj.GetType().GetField(_getBackingFieldName(propertyName), BindingFlags.Instance | BindingFlags.NonPublic);
}

I don't know what code conventions you work to, but personally, I like helper methods to be private and begin with a lower case letter. I don't find that obvious enough when reading, so I like the preceding underscore too.

There is discussion of backing fields, and their automatic naming. For the purpose of unit tests, you'll know pretty quickly if it has changed or not! It won't be catastrophic to your real code either, just the tests. So we can make simple assumptions about the naming of names—as I have above. You may disagree, and that's fine.

The more difficult helper _getBackingField returns one of those reflection types, FieldInfo. I've made an assumption here too, that the backing field you're after is from an object that's an instance, as opposed to being static. You can break that out into arguments to be passed in if you wish, but the waters will sure be muddier to the average developer who might want the functionality but not the understanding.

The handy thing about FieldInfos is that they can set fields on objects that match the FieldInfo. This is better explained with an example:

var field = _getBackingField(myObjectToChange, "State");
field.SetValue(myObjectToChange, ObjectState.Active);

In this case, the field is of an enumeration type called ObjectState. Names have been changed to protect the innocent! So, in the second line, you can see that by accessing the FieldInfo returned previously, I can call upon the SetValue method, which you might think should already relate to your object, but does not! This is the nature of reflection—FieldInfo separates a field from where it came from, so you must tell it what instance to work with (myObjectToChange) and thus, the value you want it to have, in this case, ObjectState.Active.

So to make a long story short, object-oriented programming will prevent us from doing such nasty things as accessing private fields, and worse, changing them when the developer of the code did not intend. Which is good! That's one of the reasons C# is so valuable, and liked by developers.

However, Microsoft gave us Reflection, and through it, we wield a mighty weapon. It may be ugly, and very slow, but at the same time, it exposes the innermost depths of the inner workings of MSIL (MicroSoft Intermediate Language)—IL for short—and enables us to pretty much break every rule in the book, this being a good example.

Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72
Simon Miller
  • 890
  • 7
  • 7
  • 8
    Man, you are unit testing implementation and not behavior, i.e. doing white box testing. Unit testing is supposed to help you e.g. when you want to change the implementation and not the behavior. A piece of advice is to consider your test subject a black box. Use its methods and different mocks to get it in the state you want. Just my two cents. – Johan Franzén Mar 19 '19 at 20:31
  • +1! Works as expected, also on get-only properties. But you should add some information for changing backing fields in `struct` variables: `SetValue()` takes an object, thus it boxes the struct variable and changes the field on the copy: https://stackoverflow.com/a/27226969. So you need to box the variable yourself and then assign the edited boxed variable back to the original variable. In my situation, when I had to edit a struct during debugging, it was indeed easier to create and assign a new struct to the variable. – Tobias Knauss Sep 09 '20 at 09:23
12

UPDATE: https://github.com/jbevain/mono.reflection comes with a backing-field resolver method which works with auto-properties generated by C#, VB.NET, and F#. The NuGet package is at https://www.nuget.org/packages/Mono.Reflection/

ORIGINAL: I ended up with this fairly flexible method for only C# auto-properties. As the other answers make clear, this is not portable and won't work if the compiler implementation uses a backing field naming scheme other than <PropertyName>k__BackingField. As far as I've seen, all implementations of C# compilers currently use this naming scheme. VB.NET and F# compilers use another naming scheme that won't work with this code.

private static FieldInfo GetBackingField(PropertyInfo pi) {
    if (!pi.CanRead || !pi.GetGetMethod(nonPublic:true).IsDefined(typeof(CompilerGeneratedAttribute), inherit:true))
        return null;
    var backingField = pi.DeclaringType.GetField($"<{pi.Name}>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
    if (backingField == null)
        return null;
    if (!backingField.IsDefined(typeof(CompilerGeneratedAttribute), inherit:true))
        return null;
    return backingField;
}
Nick Strupat
  • 4,928
  • 4
  • 44
  • 56
7

In Visual Studio 2010 at least, you can get the list of private fields in a class using reflection if you explicitly state that you want the non-public instance fields:

FieldInfo[] myInfo = ClassWithPostalCode.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);

You can then loop through the FieldInfo array. In this case you will see that the name of the backing field will probably be

<PostalCode>k__BackingField

I've noticed that all automatic properties seem to follow the pattern of property name in angle brackets followed by "k__BackingField", but keep in mind that this is not official and can change in future versions of .Net. I'm not entirely certain it isn't different in past versions, for that matter.

Once you know the field name, you can get its value this way:

object oValue = obj.GetType().InvokeMember(fi.Name
    , BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance
    , null, obj, null);
CD Jorgensen
  • 1,361
  • 9
  • 8
5

See the following excerpt from this document:

Automatically implemented (auto-implemented) properties automate this pattern. More specifically, non-abstract property declarations are allowed to have semicolon accessor bodies. Both accessors must be present and both must have semicolon bodies, but they can have different accessibility modifiers. When a property is specified like this, a backing field will automatically be generated for the property, and the accessors will be implemented to read from and write to that backing field. The name of the backing field is compiler generated and inaccessible to the user.

Thus, there is no way to access fields. Utilize your first approach. Auto-implemented properties are specifically for the case where you don't need to access backing field.

Krizz
  • 11,362
  • 1
  • 30
  • 43
1

Auto-implemented properties are a "lazier" version of a manually implemented property with a backing field. Since they don't allow any additional logic, the only thing you can do with them is to read or write the "hidden" private field. You can still use the private modifier to limit access to one of the accessors (usually, set would be the private one in that case), if you want your private methods to have this privilege.

If you wanted to access some other class' private fields (like a class from the BCL), you could use Reflection to do it (as explained in these examples), but it would be a nasty hack where no one would guarantee that a one-letter change in framework's source wouldn't break your code in the future.

But since you already opted to go for auto-implementation, I see no possible reason to want to access the backing field. Accessing the field directly or through the auto-implemented property accessors has no difference and no benefit. You could, for example, argue that you can use Interlocked to modify the field atomically (which you cannot do to a property), but it doesn't enforce any "thread safely" when everyone else has access to the field through the property with no atomicity.

Not to mention that compiler will most probably inline every call, so there is no performance difference either.

vgru
  • 49,838
  • 16
  • 120
  • 201
  • This is a common thing to do in VB, when you want to set the backing field value in the constructor of the class to which the auto-implemented property belongs. I agree there's no valid reason to be wanting to set it outside of the constructor. I was quite shocked (& hence the search which lead me here) to find that you couldn't do it in C#. But I'm actually confused now, because you said "the only thing you can do with them is to read or write the "hidden" private field". – Yann Duran Apr 12 '13 at 16:42
  • @Yann: I don't use VB, so I am not sure if I understood you, but there is a `readonly` modifier in C# which allows you to set the private field in constructor only. If can be only applied to fields, not properties, so there isn't a way to use it if you use auto-implemented properties. – vgru Apr 21 '13 at 20:18
0

My way to get the FieldInfo of auto property's backing field:

public static FieldInfo? GetAutoPropertyBackingField(this PropertyInfo pi, bool strictCheckIsAutoProperty = false)
{
    if (strictCheckIsAutoProperty && !StrictCheckIsAutoProperty(pi)) return null;

    var gts = pi.DeclaringType?.GetGenericArguments();
    var accessor = pi.GetGetMethod(true);
    var msilBytes = accessor?.GetMethodBody()?.GetILAsByteArray();
    var rtk = null != msilBytes
        ? accessor!.IsStatic
            ? GetAutoPropertyBakingFieldMetadataTokenInGetMethodOfStatic  (msilBytes)
            : GetAutoPropertyBakingFieldMetadataTokenInGetMethodOfInstance(msilBytes)
        : -1;

    accessor = pi.GetSetMethod(true);
    msilBytes = accessor?.GetMethodBody()?.GetILAsByteArray();
    if (null != msilBytes)
    {
        var wtk = accessor!.IsStatic
            ? GetAutoPropertyBakingFieldMetadataTokenInSetMethodOfStatic  (msilBytes)
            : GetAutoPropertyBakingFieldMetadataTokenInSetMethodOfInstance(msilBytes);

        if (-1 != wtk)
        {
            if (wtk == rtk)
            {
                var wfi = pi.Module.ResolveField(wtk, gts, null);
                if (!strictCheckIsAutoProperty || null == wfi || StrictCheckIsAutoPropertyBackingField(pi, wfi)) return wfi;
            }
            return null;
        }
    }

    if (-1 == rtk) return null;

    var rfi = pi.Module.ResolveField(rtk, gts, null);
    return !strictCheckIsAutoProperty || null == rfi || StrictCheckIsAutoPropertyBackingField(pi, rfi) ? rfi : null;
}

private static bool StrictCheckIsAutoProperty            (PropertyInfo pi)               => null != pi.GetCustomAttribute<CompilerGeneratedAttribute>();
private static bool StrictCheckIsAutoPropertyBackingField(PropertyInfo pi, FieldInfo fi) => fi.Name == "<" + pi.Name + ">k__BackingField";

private static int GetAutoPropertyBakingFieldMetadataTokenInGetMethodOfStatic  (byte[] msilBytes) => 6 == msilBytes.Length &&                                                 0x7E == msilBytes[0] && 0x2A == msilBytes[5] ? BitConverter.ToInt32(msilBytes, 1) : -1;
private static int GetAutoPropertyBakingFieldMetadataTokenInSetMethodOfStatic  (byte[] msilBytes) => 7 == msilBytes.Length &&                         0x02 == msilBytes[0] && 0x80 == msilBytes[1] && 0x2A == msilBytes[6] ? BitConverter.ToInt32(msilBytes, 2) : -1;
private static int GetAutoPropertyBakingFieldMetadataTokenInGetMethodOfInstance(byte[] msilBytes) => 7 == msilBytes.Length && 0x02 == msilBytes[0]                         && 0x7B == msilBytes[1] && 0x2A == msilBytes[6] ? BitConverter.ToInt32(msilBytes, 2) : -1;
private static int GetAutoPropertyBakingFieldMetadataTokenInSetMethodOfInstance(byte[] msilBytes) => 8 == msilBytes.Length && 0x02 == msilBytes[0] && 0x03 == msilBytes[1] && 0x7D == msilBytes[2] && 0x2A == msilBytes[7] ? BitConverter.ToInt32(msilBytes, 3) : -1;

The last 6 single line methods' code looks maybe a little messed since the browser uses a non-fixed width font.

The code does a realy strict and accurate check to find (auto)property's backing field. It also can find out the backing field of a hand-writing simple plain property which is identical to an auto-property's implementaion if you do not apply the strict check.

The 2 strict check methods are adapted to M$ dotnetfx runtimes. And such rules most likely will not change in the future since it works well so far for now and in a predictable future.

The key code uses MSIL bytes generated by compiler to find the auto property's backing field in last 4 methods. They work for M$'s dotnetfx4x and dotnet5, and maybe all M$'s dotnetfx runtimes.

If you use it with mono or other frameworks, you can peek the compiler emitted auto property's attributes, backing field's name and setter/getter's IL bytes with dnSpy or other similar tools and then modify the 6 single line methods to adapt them. And of course you can add some other strict checks to ensure the code works correct on the fx which your program is running on.

qaqz111
  • 181
  • 2
  • 7
0

No, there isn't. If you want to access the backing field, then don't use auto properties and roll your own.

From the documentation for Auto-Implemented Properties:

When you declare a property as shown in the following example, the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
Per Kastman
  • 4,466
  • 24
  • 21
0

This comes straight from the MSDN:

In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors. They also enable client code to create objects. When you declare a property as shown in the following example, the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.

So no you can't.

james lewis
  • 2,486
  • 3
  • 24
  • 30
  • 22
    The conclusion `So no you can't` is not true. It does not say anything about not being accessible. Private fields can for example still be accessed using Reflection. – Didii Jul 05 '17 at 10:27
  • 1
    "So no you can't." Simply not true. – CleanCoder Nov 18 '20 at 16:32