0

我希望能够将任何可能的类型作为函数参数传递。

现在,传递属性存在问题,例如。

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

我可以使用:nameof(Foo.Bar),但我无法在 A(Foo.Bar) 中使用 nameof。

我想确定该字符串是从属性创建的,并且我想将属性传递给 API 并在 API 中执行 nameof。

有没有可能通过函数将属性传递给nameof?我想在我的类中隐藏将属性转换为字符串,而不是准备好字符串。如何做到这一点?

编辑:线索是关于:

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

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

是什么让 [?] 有控制台输出,例如: Prop.

4

2 回答 2

2

c# 编译器在编译时使用“nameof”来查找和替换内容,因此它不会按照您的预期工作。相反,您需要在运行时使用表达式或反射来获取属性的名称。下面是一个如何使用表达式的示例:

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));
    }

像这样使用:

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();
    }
于 2016-08-03T17:41:11.093 回答
1

我认为您在nameof这里的解释有点错误。

在您的第一个示例中,该方法将始终打印T并且不依赖于T. 关键字除了用表达式的nameof字符串表示替换给它的表达式之外什么也不做。例如,我们提供nameof参数T,他将返回该表达式的字符串表示形式:T

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

一般来说,它的用法nameof是为方法提供可重构的方法/属性/...名称。

例如,将超出范围ArgumentOutOfRangeException的参数名称作为参数。

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

如果我们像上面的示例一样将名称作为硬编码字符串提供,我们在重命名参数时会出现不一致。

为了解决这个问题,我们使用nameof并且因为我们提供参数本身而不是硬编码字符串,所以它是重构安全的。

void Test(int value)
{
    if (value < 0) throw new ArgumentOutOfRangeException(nameof(value));
    // yada yada
}
于 2016-08-03T17:16:05.997 回答