简体   繁体   中英

Reasons to specify generic types in LINQ extension methods

Just out of curiosity:

Many LINQ extension methods exist as both generic and non-generic variants, for example Any and Any<> , Where and Where<> etc. Writing my queries I usually use the non-generic variants and it works fine.

What would be the cases when one has to use generic methods?

--- edit ---

PS: I am aware of the fact that internally only generic methods are called and the compiler tries to resolve the content of the generic brackets <> during compilation. My question is rather what are the cases then one has to provide the type explicitly and not to rely on the compiler's intuition?

Always. The C# compiler is smart enough to infer what the type of the method is based on the parameters. This is important when the type is anonymous, and thus has no name.

obj.SomeMethod(123); //these calls are the same
obj.SomeMethod<int>(123);

obj.SomeMethod(new { foo = 123 }); //what type would I write here?!

Edit: To be clear, you are always calling the generic method. It just looks like a non-generic method, since the compiler and Intellisense are smart.

Edit: To your updated question, you would want to be specific if you want to use a type that is not the type of the object you are passing. There are two such cases:

  1. If the parameter implements an interface, and you want to operate on that interface, not the concrete type, then you should specify the interface:

     obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
  2. If the parameter is implicitly convertible to another type, and you want to use the second type, then you should specify it:

     obj.DoSomethingElse<long> ( 123 ); //123 is actually an int, but convertible to long

On the other hand, if you need a cast to do the conversion (or you insert one anyway), then you don't need to specify:

obj.DoYetAnotherThing( (Transformed)new MyThing() ); // calls DoYetAnotherThing<Transformed>

One example I ran into today:

ObjectSet<User> users = context.Users;
var usersThatMatch = criteria.Aggregate(users, (u, c) => u.Where(c));

The above code won't work because the.Where method doesn't return an ObjectSet<User> . You could get around this one of two ways. I could call .AsQueryable() on users, to make sure it's strongly typed as an IQueryable, or I could pass specific type arguments into the Aggregate method:

criteria.Aggregate<Func<User, bool>, IEnumerable<User>>(
    PersonSet, (u, c) => u.Where(c));

Another couple of more common examples are the Cast and OfType methods, which have no way to infer what type you want, and in many cases are being called on a non-generic collection in the first place.

In general, the folks that designed the LINQ methods went out of their way to avoid the need to use explicit types in these generic methods, and for the most part you don't need to. I'd say it's best to know it's an option, but avoid doing it unless you find it necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM