带表达式的用法泛型方法的说明

时间:2012-08-23 06:24:46

标签: c# generics expression func

我想将一个强类型属性传递给一个方法,并使用此属性名作为mhy集合的字符串,所以我找到了一些代码,我可以通过强类型传递我的属性:

public static void Add<TObject, TProperty>(this NameValueCollection collection, Expression<Func<TObject, TProperty>> expression, string value)
{
    var member = expression.Body as MemberExpression;

    collection.Add(member.Member.Name, value);
}

这可行并且做我想要的,但我想知道这是如何工作的。我感兴趣的部分是方法(Add<Tobject, TProperty>)的通用参数与Func表达式的组合。有人可以向我解释这是如何工作的吗?为什么我可以将此方法称为collection.Add((MyObject m) => m.FullName, "Martijn")?为什么不必使用Add<MyObject, ???>(m => m.FullName, "Martijn")

更新: 我现在将我的方法重构为:

public static void Add<TObject>(this NameValueCollection collection, Expression<Func<TObject, string>> expression, string value)
{
    var member = expression.Body as MemberExpression;

    collection.Add(member.Member.Name, value);
}

1 个答案:

答案 0 :(得分:1)

Expression<T>表达式树,其签名为委托类型T。表达式树很复杂,但基本上:不是作为操作的委托,而是描述操作的对象模型,可以检查以查看它是如何组成的。

因此,Expression<Func<TObject,TProperty>>是一个表达式树,表示接受TObject参数并返回TProperty结果的内容。

至于为什么你不需要手动告诉它<MyObject, ???>:这是通用类型推断,并且是正常的。给出一个通用的方法,比如说:

void Foo<T>(T bar);

可以将其称为:

Foo<string>("abc");

但您也可以使用:

Foo("abc");

然后,编译器将检查参数以查看它是否可以解析所有泛型类型参数 - 在这种情况下,"abc"string而引脚Tstring。如果它可以解析它们的 所有 ,则无需指定它们。

在您的示例中,TObject被固定,因为您的lambda明确地通过MyObject获取(MyObject) m,并且TProperty固定为(大概)a {{ 1}},因为string(推测)会返回m.FullName。由于所有通用类型参数都已自动解析,因此您无需手动指定string

请注意,泛型类型推断仅适用于通用方法(通过参数),而不适用于通用类型