在LINQ扩展方法中指定泛型类型的原因
本文关键字:泛型类型 LINQ 扩展 方法 | 更新日期: 2023-09-27 18:00:41
只是出于好奇:
许多LINQ扩展方法同时存在于泛型和非泛型变体中,例如Any
和Any<>
、Where
和Where<>
等。在编写查询时,我通常使用非泛型变体,而且效果很好。
当一个人必须使用通用方法时,会出现什么情况?
---编辑---
p。S.:我知道这样一个事实,即在内部只调用泛型方法,编译器会在编译过程中尝试解析泛型括号<>
的内容。我的问题是,如果必须显式提供类型而不依赖编译器的直觉,那么情况是什么
始终。C#编译器足够聪明,可以根据参数推断出方法的类型。当类型是匿名的,因此没有名称时,这一点很重要。
obj.SomeMethod(123); //these calls are the same
obj.SomeMethod<int>(123);
obj.SomeMethod(new { foo = 123 }); //what type would I write here?!
编辑:要明确的是,总是调用泛型方法。它看起来只是一个非泛型方法,因为编译器和Intellisense是智能的。
编辑:对于您更新的问题,如果您想使用与您传递的对象类型不同的类型,您需要具体说明。有两种情况:
如果参数实现了一个接口,并且您希望在该接口上操作,而不是在具体类型上操作,那么您应该指定接口:
obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
如果参数可以隐式转换为另一种类型,并且您希望使用第二种类型,那么您应该指定它:
obj.DoSomethingElse<long> ( 123 ); //123 is actually an int, but convertible to long
另一方面,如果您需要一个转换(或者您无论如何都插入一个),则不需要指定:
obj.DoYetAnotherThing( (Transformed)new MyThing() ); // calls DoYetAnotherThing<Transformed>
我今天遇到的一个例子:
ObjectSet<User> users = context.Users;
var usersThatMatch = criteria.Aggregate(users, (u, c) => u.Where(c));
上面的代码将不起作用,因为。Where方法不返回ObjectSet<User>
。你可以通过两种方式中的一种绕过这一点。我可以对用户调用.AsQueryable()
,以确保它是强类型的IQueryable,或者我可以将特定类型的参数传递到Aggregate方法:
criteria.Aggregate<Func<User, bool>, IEnumerable<User>>(
PersonSet, (u, c) => u.Where(c));
另外两个更常见的例子是Cast
和OfType
方法,它们无法推断您想要的类型,在许多情况下,它们首先是在非泛型集合上调用的。
一般来说,设计LINQ方法的人竭尽全力避免在这些通用方法中使用显式类型,而且在大多数情况下你不需要这样做。我认为最好知道这是一种选择,但除非你觉得有必要,否则不要这样做。