nameof(order.User.Age)仅返回“Age”而不是“order.User.Age”
以更有限的方式做到这一点的原因是什么? 如果我们只想要姓氏,我们可以做类似
的事情public static GetLastName(this string x) {
return string.Split(x, '.').Last();
}
nameof(order.User.Age).GetLastName()
有了一个操作员,我们可以同时获得“Age”和“order.User.Age”。 但是根据目前的实施情况,我们只能获得“年龄”。
这个决定背后有什么逻辑吗?
编辑:例如,MVC绑定需要此类行为
Html.TextBox(nameof(order.User.Age))
答案 0 :(得分:15)
请注意,如果您需要/需要"完整"名字,你可以这样做:
$"{nameof(order)}.{nameof(User)}.{nameof(Age)}".GetLastName();
只要所有这些名称都在当前范围内。
显然在这种情况下它并没有真正有用(名字不会在Razor调用中占据范围),但可能是你需要,例如,完整的命名空间限定名称调用Type.GetType()
或类似内容的类型。
如果名称不在范围内,你仍然可以做得更笨重:
$"{nameof(order)}.{nameof(order.User)}.{nameof(order.User.Age)}".GetLastName();
- 虽然机会中至少有一个应该在范围内(除非User.Age
是静态属性)。
答案 1 :(得分:8)
因为它正是为它所发明的。正如您在already linked discussions中所读到的那样,您可以使用nameof
作为nameof(member-access)
的{{1}}运算符,其中E.I<A1…AK>
将返回:
使用简单名称查找规则$ 7.6.2或成员访问$ 7.6.4解决了这些情况。如果他们成功绑定,他们必须绑定到以下之一:
- 方法组。这会产生错误&#34;要指定方法的名称,您必须提供其参数&#34;。
- 变量,值,参数,常量,枚举成员,属性访问,字段,事件,类型参数,命名空间或类型。 在这种情况下,nameof运算符的结果只是&#34; I&#34; ,它通常是参数绑定到的符号的名称。有一些警告......
因此,在这种情况下,根据其定义,它必须在所有点之前逐步评估所有表达式,然后评估最后一个表达式以获得其Name
:
order.User.Age --> User.Age --> Age
答案 2 :(得分:3)
使用nameof
的一些重要目的是获取最后一个&#34;名称&#34;在表达中。
例如,在抛出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)); }
}
答案 3 :(得分:3)
看看这个方法取自:
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");
}
答案 4 :(得分:1)
我遇到了同样的问题,并实现了一个类来替换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);