在审查 github 上的一些代码时,我遇到了这种模式:
using System.Linq.Expressions;
public T SomeGenericMethod<TValue>(Expression<Func<T, TValue>> myExpr){
// ...
}
这是代码中唯一相关的部分。 TValue
实际上从未在方法主体中使用过,它仅在Func<,>
中使用。类型。
它的使用如下所示:
myObj.SomeGenericMethod(x => x.SomeProperty)
请注意,调用 SomeGenericMethod
时不会传递泛型。 。我本来期望编译器需要类似的东西:
myObj.SomeGenericMethod<SomeTValue>(x => x.SomeProperty)
但事实并非如此。
所以我的问题是,TValue
是什么?当没有任何内容作为类型显式传递给泛型方法调用时?
最佳答案
在本例中,它是typeof(SomeProperty)
。 C# 编译器会自动发现它。来自 https://msdn.microsoft.com/en-us/library/twcad0zb.aspx
You can also omit the type argument and the compiler will infer it.
The compiler can infer the type parameters based on the method arguments you pass in; it cannot infer the type parameters only from a constraint or return value. Therefore type inference does not work with methods that have no parameters. Type inference occurs at compile time before the compiler tries to resolve overloaded method signatures. The compiler applies type inference logic to all generic methods that share the same name. In the overload resolution step, the compiler includes only those generic methods on which type inference succeeded.
请注意,您可能会认为这种用法很奇怪,但是当您使用 LINQ 时,您会正常这样做。使用 Line 你可以写:
var coll = new[] { new { Foo = 1, Bar = 2 } };
var enu = coll.Select(x => x.Foo).ToList();
您没有在 Select
中的任何地方明确说明 Foo
的类型。编译器推断它是一个int
。
Select
的签名是:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
因此 Foo
的类型是 TResult
如果没有这种类型推断,匿名对象几乎毫无用处,因为你不能:
class MyClass
{
public int Foo { get; set; }
public int Bar { get; set; }
}
var coll = new[] { new MyClass { Foo = 1, Bar = 2 } };
var enu = coll.Select<MyClass, ???>(x => new { Bar = x.Foo }).ToList();
你会在???
中放入什么?根据匿名对象的定义,您无法显式命名它们:-)
关于c# - 未显式传递时通用类型的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29750060/