40

Given this class:

public class MyClass
{
    public int MyProperty {get; set;}
}

How will I be able to extract the name of MyProperty in code?

For example, I am able to get the name of the class like this

typeof(MyClass).Name

How can I do something similar for the property?

The reason for the question is that I want this particular code to be resistant against refactorizations of the names.

EDIT: With resistant I mean that I want the code at the call site to be robust in the face of changes of the propertyname. I have some stuff that is using a string representation of the property name. Sorry for the poor phrasing. I did not include call site code in order to keep the problem clean and not wander off into other discussions on the nature of the call site code.

6
  • Is this for INotifyPropertyChanged support? Commented Sep 29, 2011 at 14:39
  • just use reflection, see examples in SO, like this one: stackoverflow.com/questions/1120839/… Commented Sep 29, 2011 at 14:39
  • added an edit to answer your questins and suggestions. Commented Sep 29, 2011 at 16:31
  • 2
    what you describe is not a field. its a property Commented Apr 27, 2019 at 13:35
  • 1
    @BoppityBop sorry, had a bad day, corrected the question to reflect that we are talking about properties and not a field. Commented Apr 30, 2019 at 8:31

7 Answers 7

64

In C# 6 we can do it very simply

nameof(MyField);

you can get method\type\propery\field\class\namespace names in the same way ex

 nameof(MyClass);
 nameof(namespacename1)  // returns "namespacename1"
 nameof(TestEnum.FirstValue) // returns enum's first value

MSDN Reference

Look at this post

Sign up to request clarification or add additional context in comments.

5 Comments

Much better solution. Make sure, if you're using Continuous Integration (like Jenkins or so), to use at least MSBuild version 14.0 in order to compile there too, otherwise it'll only compile in your dev machine. Perks of using C# 6.0
much much better.
This is done at compile time. There may be reasons to want to do it dynamically at runtime as @John Leidegren showed. Eg if using an obfuscator etc, the compile time names would change.
why are you upvoting a stolen answer? look the timestamp
stackoverflow shows answers by repution or timestap ??
57

You do it like this, using compiler generated expression trees:

public static string GetMemberName<T, TValue>(Expression<Func<T, TValue>> memberAccess)
{
    return ((MemberExpression)memberAccess.Body).Member.Name;
}

Now call the static method from code:

class MyClass
{
    public int Field;
    public string Property { get; set; }
}

var fieldName = GetMemberName((MyClass c) => c.Field);
var propertyName = GetMemberName((MyClass c) => c.Property);
// fieldName has string value of `Field`
// propertyName has string value of `Property`

You can now also use refactoring to rename that field without breaking this code

4 Comments

What's the chance to do something like that in Java? Or is it something C# unique (as I've seen so far)?
@VitaliPom I don't know a lot about Java. This is generated by the C# compiler. Pretty C# unique stuff, probably not something Java can do other JVM languages surly can. Would be surprised if not.
How slow is this? Would it be worth caching somehow?
@rolls slow and expensive, but measure first! Use the nameof feature of C# if possible, it can be used to reference instance members, like this nameof(MyClass.Field) => "Field"
29

With C# 6.0, you can use the new nameof operator.

nameof(MyClass.MyField)  // returns "MyField"
nameof(MyClass)  //returns "MyClass"

See nameof (C# and Visual Basic Reference) for more examples.

Comments

10

Using Reflection you can find all Members from MyClass with this.

    MemberInfo[] members = typeof(MyClass).GetMembers();

Now you can find your desired property for each Member.

    foreach ( MemberInfo memberInfo in members)
    {
        Console.WriteLine("Name: {0}", memberInfo.Name); // Name: MyField
        Console.WriteLine("Member Type: {0}", memberInfo.MemberType); // Member Type: Property
    }

If you want to find only Properties use PropertyInfo instead of MemberInfo. Or write this

    foreach ( MemberInfo memberInfo in members.Where(p => p.MemberType == MemberTypes.Property))
    {
        Console.WriteLine("Name: {0}", memberInfo.Name); // Name: MyField
        Console.WriteLine("Member Type: {0}", memberInfo.MemberType); // Member Type: Property
    }

2 Comments

Please consider editing your post to add more explanation about what your code does and why it will solve the problem. An answer that mostly just contains code (even if it's working) usually wont help the OP to understand their problem.
it works as intended just don’t forget to add using System.Linq;
5

You could use the following class which contains a method using an expression tree as an argument to determine a member name based on a lambda expression:

public class MemberHelper<T>
{
    public string GetName<U>(Expression<Func<T, U>> expression)
    {
        MemberExpression memberExpression = expression.Body as MemberExpression;
        if (memberExpression != null)
            return memberExpression.Member.Name;

        throw new InvalidOperationException("Member expression expected");
    }
}

Then use it like so:

MemberHelper<MyClass> memberHelper = new MemberHelper<MyClass>();
string name = memberHelper.GetName(x => x.MyField);

5 Comments

Using an instance is actually a good idea, you don't have to repeat the type name all over the place but the type constraint is unnecessary. e.g. why wouldn't this work for structs?
@CarstenKönig: you should? I don't think that makes sense. Users should free to remove things if they think it doesn't add value. However, the MemberHelper idea could help to get significantly smoother syntax at the call site. It is not useless as an answer.
@John Leidegren - Your right, I originally wrote this class for use with classes and didn't think about its potential use with structs too. Have amended the answer to reflect your suggestion.
@sehe - ok you got a point - think is (and this happens to me a lot) - if you get unlucky and post basically the same idea seconds after another you will get downvotes very fast ... this is why I canceled my 99% ready answer with the same content - in this case everything seems just fine so I remove my comment instead ;)
This is as good an answer as the other one I marked - it solves my problem too. He was one minute faster on the trigger ;)
3

If you only want to get name of an instance member, you can use shorter code:

    public static string GetMemberName<TValue>(Expression<Func<TValue>> memberAccess)
    {
        return ((MemberExpression)memberAccess.Body).Member.Name;
    }

And use it like the following inside the class:

    ReflectionTools.GetMemberName(() => _someInstanceVariableOrProperty)

Comments

1

If you don’t want to waste your time, try the following one. I know there will be people run into the same problem.

// Soner - tested!
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(item))
{
    string name = descriptor.Name;              // Name
    object value = descriptor.GetValue(item);   // Value
    var type = descriptor.PropertyType;         // Type
    Console.WriteLine($"{name}={value}={type}");
}

Don’t forget to add using System.ComponentModel;.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.