Search code examples
c#reflectionkeywordlanguage-features

Partial implemention through code of C#6's nameof functionality in earlier versions of C#?


"nameof" is an amazing idea which would be good to replicate in previous versions even if partially.

I am particularly interested in public property names like:

public class MyClass
{
    public SomeType Myproperty {get;set;}
}


static Main()
{
    MyClass myClass = new MyClass();

    Console.WriteLine(Utilities.NameOf(myClass.MyProperty)); //Writes "MyProperty".
    Console.ReadKey();
}

Is there a way to do this (maybe through reflection etc.)? If we could do this, it would also prepare our code for when we upgrade to C#6 in the future by simply replacing Utilities.NameOf with nameof.


Solution

  • Thanks to Alexei Levenkov for pointing to the right direction,

    Schotime's for his answer in this question and

    agent-j's for his answer in this question

    there is a simple and elegant solution that has two versions:

    public static class Util
    {
        public static string NameOf<TProperty>(Expression<Func<TProperty>> e)
        {
            return (e.Body as MemberExpression).Member.Name;
        }
    
        public static string NameOf<TClass, TProperty>(Expression<Func<TClass, TProperty>> e)
        {
            return (e.Body as MemberExpression).Member.Name;
        }
    }
    

    and can be used so:

    public class MyClass
    {
        public SomeProperty MyProperty { get; set; }
    }
    
    
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();
    
    
        string case1 = Util.NameOf(() => myClass.MyProperty);       //Case1 when an instance is available 250x
        string case2 = Util.NameOf(() => (null as MyClass).MyProperty); //Case2 when no instance is available 175x
        string case3 = Util.NameOf((MyClass c) => c.MyProperty);        //Case3 when no instance is available 330x
    
        string caseTest = "MyProperty";     //Test case 1x
    
    }
    

    At the end of each case, the number shows how much slower each call is relative to a literal string assignment.

    This was done by assigning the return values of each call to an array of strings and comparing that to the literal string assignment of the same value "MyProperty".

    Case2 seems to be the winner.