Search code examples
c#propertiesabstract-classdefault-valuegetter

Get the default value of a property of an abstract class


Is there a way in C# to access the default value of a non-static, non-const property that is defined in an abstract class?

For example, given:

public abstract class SomeClass
{
    public int SomeProperty { get; set; } = 99;
}

I would like something similar to the following to return "99":

default(SomeClass.SomeProperty);

I know that the default() operator doesn't work like this and the above results in compiler error. What the default() operator can do is return the default value for SomeClass, which naturally is null for reference types, therefore:

default(Test).SomeProperty;

can be compiled but rightly throws a NullReferenceException.

Note some assumptions for the context of this question:

  • the abstract class definition is not easily modifiable by me. It sits in an external library, to which I can propose changes, but it takes a long process of review/justification to apply such changes. This is why I would much favour solutions that do not require its modification.
    I still appreciate suggestions that could work by modifying it. I have already considered using an Attribute to store the default value and fetching it via Reflection.
  • Please consider that there is no available concrete implementation of the abstract class.

I already imagine that the answer to the main question is "no". However, it would be great to get insights from experts as per whether a feature for this could be (or has been) considered for implementation in C#, or if there are intrinsic language limitations that would prevent it from working, or simply it would have too scarce demand to justify an implementation.


Solution

  • Accessing this = 99 would require either:

    1. using a Roslyn analyzer and inspecting the source at build-time
    2. reading the IL of the constructor body at runtime, and interpreting the opcodes

    The first option is probably easier; you can see an example of this in protobuf-net.BuildTools, which checks for this usage, and raises a flag if there is not a matching [DefaultValue(...)]; a [DefaultValue(...)] is trivial to inspect at runtime.