Why do I need to cast a dynamic object when calling IEnumerable.Contains()?

I am trying to call IEnumerable.Contains() with a dynamic argument, but I am getting the error

'IEnumerable' does not contain a definition for 'Contains' and the best extension method overload 'Queryable.Contains(IQueryable, TSource)' has some invalid arguments

I've noticed that I can either cast the argument to the correct type, or use an underlying collection type to fix the issue. But I'm not sure why I can't just pass in the argument directly.

dynamic d = "test";
var s = new HashSet<string>();
IEnumerable<string> ie = s;

s.Contains(d);           // Works
ie.Contains(d);          // Does not work
ie.Contains((string)d);  // Works
Jon Skeet
people
quotationmark

Enumerable.Contains is an extension method - and extension methods aren't resolved by the mini-compiler which is used at execution time. (Execution methods depend on using directives, which aren't preserved. They could be, but I guess that was seen as a bit painful.) This includes both using dynamic arguments to extension methods, and on using them as the "target" of extension methods.

Just specify the extension method directly instead:

var result = Enumerable.Contains(ie, d);

people

See more on this question at Stackoverflow