出于好奇:
许多LINQ扩展方法作为通用和非泛型变体存在,例如Any
和Any<>
,Where
和Where<>
等。编写我的查询我经常使用非泛型变体,它工作正常。
当必须使用通用方法时会出现什么情况?
---编辑---
P.S。:我知道内部只调用泛型方法,编译器尝试在编译期间解析通用括号<>
的内容。
我的问题是,那么案例是什么,然后必须明确提供类型而不是依赖编译器的直觉?
答案 0 :(得分:5)
始终。 C#编译器非常智能,可以根据参数推断出方法的类型。当类型是匿名的,因此没有名称时,这很重要。
obj.SomeMethod(123); //these calls are the same
obj.SomeMethod<int>(123);
obj.SomeMethod(new { foo = 123 }); //what type would I write here?!
编辑:要清楚,您总是调用泛型方法。它看起来像一个非泛型方法,因为编译器和智能感知是聪明的。
编辑:对于您更新的问题,如果您想使用的类型不是您传递的对象的类型,那么您可能希望具体。有两种这样的情况:
如果参数实现了一个接口,并且你想在该接口上操作,而不是具体类型,那么你应该指定接口:
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>
答案 1 :(得分:3)
我今天遇到的一个例子:
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方法的人们不遗余力地避免在这些通用方法中使用显式类型,并且大多数情况下你不需要这样做。我会说最好知道这是一个选项,但除非你认为有必要,否则不要这样做。