简体   繁体   中英

Pass property as function argument and convert it name to string inside

I would like to be able to pass any possible type as function parameter.

Now, there is problem with passing property eg.

class Foo
{
    public int Bar { get; set; }
}

I'm able to use: nameof(Foo.Bar) but I'm unable to do A(Foo.Bar) where in A will be used nameof.

I want to have sure that string is created from property and I would like to have property passed to API and do nameof inside API.

Is there any possibility to pass property through function to nameof? I would like to hide converting of property to string inside of my class instead of getting ready string. How achieve that?

edit: The clue is about:

class B
{
    public Prop {get; set;}
}

void foo([?])
{
    Console.WriteLine(nameof([?]));
}

What put instead [?] to have console output like: Prop.

I think you are interpreting nameof a little bit wrong here.

In your first example the method will always print T and does not depend on the type of T . The nameof keyword does nothing other than replacing the expression given to it by a string representation of the expression. eg we are giving nameof the parameter T and he will return the string representation of that expression: T .

void A<T>(T smth)
{
   Console.Writeline(nameof(T)); // example usage
}

In general the usage of nameof is to provide refactor-able method/property/... names to methods.

For example the ArgumentOutOfRangeException has as parameter the name of the argument that is out of range .

void Test(int value)
{
    if (value < 0) throw new ArgumentOutOfRangeException("value");
    // yada yada
}

If we provide the name as hardcoded string as in the example above we would get an inconsistency when renaming the parameter.

In order to solve this we use nameof and because we are providing the parameter itself instead of a hardcoded string it is refactor safe.

void Test(int value)
{
    if (value < 0) throw new ArgumentOutOfRangeException(nameof(value));
    // yada yada
}

The c# compiler uses 'nameof' to kind of find and replace things at compile time, so it won't work how you expect it to. Instead you'll need to get the names of the properties at run-time using either Expressions or Reflection. Here's an example of how to do it using Expressions:

public static string GetName<T>(Expression<Func<T>> expression)
    {
        var member = (MemberExpression)expression.Body;
        return member.Member.Name;
    }
    public static string GetName<T>(Expression<Func<T, object>> expression)
    {
        var body = expression.Body as MemberExpression;

        if (body == null)
        {
            body = ((UnaryExpression)expression.Body).Operand as MemberExpression;
        }

        return body.Member.Name;
    }

    public static void PrintName<T>(Expression<Func<T>> expression)
    { 
        Console.WriteLine(GetName(expression));
    }

    public static void PrintName<T>(Expression<Func<T, object>> expression)
    { 
        Console.WriteLine(GetName(expression));
    }

Used like this:

class B
{
    public Prop {get; set;}
}

static void Main(string[] args)
    { 
        PrintName<B>((b) => b.Prop); 

        //Or
        var someObject = new B();
        PrintName(() => someObject.Prop); 

        Console.ReadLine();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM