1

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

P.S.: 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?

Alexander Galkin
  • 12,086
  • 12
  • 63
  • 115
  • 1
    I'm not sure who downvoted you, but it would probably help to re-word the original question title and text to indicate that you're talking about when to *specify* the type parameters, rather than "generic and non-generic variants" of the LINQ methods. – StriplingWarrior Jun 29 '11 at 01:02
  • @StriplingWarrior: I tried to edit the title according to your suggestion. Does it sound clearer to you now? – Alexander Galkin Jun 29 '11 at 01:10
  • Yes. Just be aware that there are actually "non-generic variants" like the `IList.Contains` method (http://msdn.microsoft.com/en-us/library/system.collections.ilist.contains.aspx), which could easily be confused for LINQ methods. – StriplingWarrior Jun 29 '11 at 01:20

2 Answers2

5

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>
Mike Caron
  • 14,351
  • 4
  • 49
  • 77
  • Thank you a lot. I am aware of the fact that internally the generic method invocation is resolved by the compiler. My question targets rather the cases WHEN if would bring any benefits to indicate the type explicitly. Like if the compiler tries to resolve the type to some kind of interface and one really would like to use the methods and properties of the derived type etc. I editted my question to make it clearer. – Alexander Galkin Jun 29 '11 at 00:51
  • I think that should answer your questions. It should be noted that the compiler will never infer an interface from a concrete type. It will only infer an interface if the type you give it is also an interface. – Mike Caron Jun 29 '11 at 01:04
  • Great, thank you for adding some more examples, it helped me a lot! – Alexander Galkin Jun 29 '11 at 01:12
3

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.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315