44

nameof(order.User.Age)只返回Age而不是order.User.Age

以更受限制的方式进行操作的原因是什么?如果我们只想要姓氏,我们可以做类似的事情

public static GetLastName(this string x) { 
    return string.Split(x, '.').Last();
}

nameof(order.User.Age).GetLastName()

使用一个运算符,我们可以同时得到Ageorder.User.Age。但是在当前的实现中,我们只能得到Age. 这个决定背后有什么逻辑吗?例如,这种行为对于 MVC 绑定是必需的

Html.TextBox(nameof(order.User.Age))
4

5 回答 5

24

请注意,如果您需要/想要“完整”名称,您可以这样做:

$"{nameof(order)}.{nameof(User)}.{nameof(Age)}".GetLastName();

只要所有这些名称都在当前范围内

显然,在这种情况下,它并不是真的很有帮助(名称不会在 Razor 调用的范围内),但如果您需要,例如,用于调用的类型的完整命名空间限定名称Type.GetType()或其他东西,它可能是有用的.

如果名称不在范围内,您仍然可以做一些更笨重的事情:

$"{nameof(order)}.{nameof(order.User)}.{nameof(order.User.Age)}".GetLastName();

- 尽管机会至少其中一个应该在范围内(除非User.Age是静态属性)。

于 2016-07-18T23:48:20.867 回答
10

因为它正是被发明出来的。正如您在已经链接的讨论中所读到的那样,在这里您使用nameof操作符 as nameof(member-access),形式为E.I<A1…AK>,它将返回:

这些情况都可以使用简单名称查找 $7.6.2 或成员访问 $7.6.4 的规则来解决。如果它们成功绑定,它们必须绑定到以下之一:

  • 一个方法组。这会产生错误“要指定方法的名称,您必须提供其参数”。
  • 变量、值、参数、常量、枚举成员、属性访问、字段、事件、类型参数、命名空间或类型。在这种情况下,nameof 运算符的结果就是简单的 "I",它通常是参数绑定到的符号的名称。有一些警告......</li>

所以在这种情况下,根据它的定义,它必须逐步评估所有点之前的所有表达式,然后评估最后一个以获得它的Name

order.User.Age --> User.Age --> Age
于 2015-01-12T13:43:17.957 回答
10

我遇到了同样的问题,并实现了一个类来替换nameof()关键字,以获取所提供表达式的全名。它的灵感来自 OK HOSTING 答案。它刚刚烤好并可以使用:

public static class NameOf<TSource>
{
    #region Public Methods

    public static string Full(Expression<Func<TSource, object>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
        {
            var unaryExpression = expression.Body as UnaryExpression;
            if (unaryExpression != null && unaryExpression.NodeType == ExpressionType.Convert)
                memberExpression = unaryExpression.Operand as MemberExpression;
        }

        var result = memberExpression.ToString();
        result = result.Substring(result.IndexOf('.') + 1);

        return result;
    }

    public static string Full(string sourceFieldName, Expression<Func<TSource, object>> expression)
    {
        var result = Full(expression);
        result = string.IsNullOrEmpty(sourceFieldName) ? result : sourceFieldName + "." + result;
        return result;
    }

    #endregion
}

在您的代码中使用它看起来像:

class SpeciesFamily
{
    public string Name { get; set; }
}

class Species
{
    public SpeciesFamily Family { get; set; }
    public string Name { get; set; }
}

class Cat
{
    public Species Species { get; set; }
}

// Will return a string containing "Species.Family.Name".
var fullName = NameOf<Cat>.Full(c => c.Species.Family.Name);

// Will return a string containing "cat.Species.Name".
var fullNameWithPrefix = NameOf<Cat>.Full("cat", c => c.Species.Name);
于 2019-10-01T18:42:34.173 回答
5

看看这个方法取自:

https://github.com/okhosting/OKHOSTING.Data/blob/master/src/PCL/OKHOSTING.Data/Validation/MemberExpression.cs

public static string GetMemberString(System.Linq.Expressions.Expression<Func<T, object>> member)
    {
        if (member == null)
        {
            throw new ArgumentNullException("member");
        }

        var propertyRefExpr = member.Body;
        var memberExpr = propertyRefExpr as System.Linq.Expressions.MemberExpression;

        if (memberExpr == null)
        {
            var unaryExpr = propertyRefExpr as System.Linq.Expressions.UnaryExpression;

            if (unaryExpr != null && unaryExpr.NodeType == System.Linq.Expressions.ExpressionType.Convert)
            {
                memberExpr = unaryExpr.Operand as System.Linq.Expressions.MemberExpression;

                if(memberExpr != null)
                {
                    return memberExpr.Member.Name;
                }
            }
        }
        else
        {
            //gets something line "m.Field1.Field2.Field3", from here we just remove the prefix "m."
            string body = member.Body.ToString();
            return body.Substring(body.IndexOf('.') + 1);
        }

        throw new ArgumentException("No property reference expression was found.", "member");
    }
于 2016-03-19T03:57:42.577 回答
4

使用的一些重要目的nameof是获取表达式中的最后一个“名称”。

例如抛出时的 nameof 参数ArgumentNullException

void Method(string parameter)
{
     if (parameter == null) throw new ArgumentNullException(nameof(parameter));
}

MVC 动作链接

<%= Html.ActionLink("Sign up",
    @typeof(UserController),
    @nameof(UserController.SignUp))
%>

INotifyPropertyChanged

int p {
    get { return this._p; }
    set { this._p = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.p)); }
}

更多信息:https ://roslyn.codeplex.com/discussions/570551

于 2015-01-12T08:56:06.467 回答