public void GiveMeAProp(Expression<Func<TInstance,TProp>> prop)


通常用作说“请给我一个属性选择器”的标准方式。但是有很多东西可以满足这个签名,但实际上不是“真实”属性。例如以下所有内容均可编译。

GiveMeAProp(x => Method());
GiveMeAProp((x) => localVariable);
GiveMeAProp(x => x);
GiveMeAProp(x => (Type)x);
GiveMeAProp((x) => !x.BooleanProp);


我当然可以简单地声明我的方法采用MemberExpression,但是随后我失去了表达式的严格类型,尤其是失去了编写的能力:

public void SetThisProp(Expression<Func<TInstance,TProp>> prop, TProp value)


我可以进行运行时检查,以确保最终得到的表达式的Body是MemberExpression,但是如果我可以让类型系统为我强制执行该表达式,那将非常好吗?在我的用例中,没有其他类型的Expression<T>实际上是有效的参数。

问题:无论如何,我是否可以静态地强制参数表示MemberExpression并返回类型T

最佳答案

无论如何,我是否可以静态地强制参数表示MemberExpression并返回类型T?


不,目前不在C#中。

很难证明是否定的,但是我认为从所有遵循您引用的模式的各种库中可以很清楚地看出这是最佳方法。如果有更好的方法,我认为到现在它会流行很多。

对于eaxmple来说,"OrderBy" method in Linq是一个非常经典的示例,如您在此处所做的那样,库以类型安全的方式请求属性,它们并没有设法避免您引用的相同陷阱:

public static System.Linq.IOrderedQueryable<TSource> OrderBy<TSource,TKey> (this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<Func<TSource,TKey>> keySelector);

var studentsOrderByRank = students.OrderBy(w => w.Rank);


以下将编译,但在运行时失败:

string localVar = "example";
var studentsOrderByRank = students.OrderBy(w => localVar);


我认为,只要您的库在运行时给出明确的错误消息(如果用户通过的Expression<Func<TInstance,TProp>>实际上不是属性访问权限),这就是您所能做到的。

有关重新使用这些表达式的库中的最佳实践,另请参见this answer

07-24 18:44