在LINQ扩展方法中指定泛型类型的原因

本文关键字:泛型类型 LINQ 扩展 方法 | 更新日期: 2023-09-27 18:00:41

只是出于好奇:

许多LINQ扩展方法同时存在于泛型和非泛型变体中,例如AnyAny<>WhereWhere<>等。在编写查询时,我通常使用非泛型变体,而且效果很好。

当一个人必须使用通用方法时,会出现什么情况?

---编辑---

p。S.:我知道这样一个事实,即在内部只调用泛型方法,编译器会在编译过程中尝试解析泛型括号<>的内容。我的问题是,如果必须显式提供类型而不依赖编译器的直觉,那么情况是什么

在LINQ扩展方法中指定泛型类型的原因

始终。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是智能的。

编辑:对于您更新的问题,如果您想使用与您传递的对象类型不同的类型,您需要具体说明。有两种情况:

  1. 如果参数实现了一个接口,并且您希望在该接口上操作,而不是在具体类型上操作,那么您应该指定接口:

    obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
    
  2. 如果参数可以隐式转换为另一种类型,并且您希望使用第二种类型,那么您应该指定它:

    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));

另外两个更常见的例子是CastOfType方法,它们无法推断您想要的类型,在许多情况下,它们首先是在非泛型集合上调用的。

一般来说,设计LINQ方法的人竭尽全力避免在这些通用方法中使用显式类型,而且在大多数情况下你不需要这样做。我认为最好知道这是一种选择,但除非你觉得有必要,否则不要这样做。