Get name of a property and declaring class

How can I use reflection to get the name and declaring class of a property of a generic type. The purpose is to get an exception if I read a property where nothing has been written so far. One of the problems is that the check must be independent of the declaring class.

value.GetType().DeclaringType is always null.

using System;

namespace TestCodeContract
{

    public struct CheckForNull<T> where T : struct
    {
        private T? backingField;

        public static implicit operator T(CheckForNull<T> value)
        {
            if (!(value.backingField.HasValue))
            {
                var t1 = value.GetType().DeclaringType; // always null.

                var propertyName = "Delta"; // TODO get from Reflection
                var className = "ContractClass"; // TODO get from Reflection
                var msg = String.Format("Proprety '{0}' in class '{1}' is not initialized", propertyName, className);
                throw new ApplicationException(msg);
            }
            return value.backingField.Value;
        }

        public static implicit operator CheckForNull<T>(T value)
        {
            return new CheckForNull<T> { backingField = value };
        }
    }

    public class ContractClass
    {
        public CheckForNull<int> Delta { get; set; }

        public void Test1()
        {
            int x = Delta; // Wanted: "Property 'Delta' in class 'ContractClass' is not initialized"
        }
    }
}
Jon Skeet
people
quotationmark

No, you can't do it like that. I would suggest something like this instead:

// You could do this without the constraint, with a bit of extra work.
public class ReadOnlyAfterWrite<T> where T : struct
{
    private T? value;
    private readonly string property;
    private readonly string type;

    public ReadOnlyAfterWrite(string property, string type)
    {
        this.property = property;
        this.type = type;
    }

    public T Value
    {
        get
        {
            if (value == null)
            {
                // Use type and property here
                throw new InvalidOperationException(...);
            }
            return (T) value;
        }
        set { this.value = value; }
    }
}

public class ContractClass
{
    // This is what I'd do in C# 6. Before that, probably just use string literals.
    private readonly ReadOnlyAfterWrite<int> delta =
        new ReadOnlyAfterWrite(nameof(Delta), nameof(ContractClass));

    public int Delta
    {
        get { return delta.Value; }
        set { delta.Value = value; }
    }
}

While it's not terribly clean in implementation, I think it's a better public API - the fact that it's guarded is invisible to the caller, who just sees an int property.

people

See more on this question at Stackoverflow