使用表达式解释泛型方法的用法



我想将强类型属性传递给一个方法,并将此属性名称用作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);
}

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) m显式获取MyObject,而TProperty被固定到(可能)string,因为m.FullName(可能)返回string。由于所有泛型类型参数都已自动解析,因此不需要手动指定<...>

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

最新更新