Does LINQ Query Syntax support Duck Typing?

Regarding LINQ query syntax ...

var foo = new List<int> { 1, 2 }; var boo = from n in foo where n > 1 select n; 

... I have always believed that this syntax is limited to IEnumerable . Or at least until I found out about IQueryable. And maybe IObservable. But recently, I noticed a suggestion that the query syntax is based on a duck set . This story did not look terribly convincing until I found a site dedicated to LINQ to Tasks . LINQ to Tasks looks like it is completely dependent on duck print with query syntax!

Well, what's going on here? Is the query syntax using duck input or not? When I give it a try, I'm pretty sure it works, and it all seems to prove that the duck is printing, not IEnumerable:

 public class Joker<T> { public T Item; public Joker(T item) { Item = item; } } public static class JokerHelp { public static T2 Select<T,T2>(this Joker<T> joke, Func<T,T2> call) { return call(joke.Item); } } var oof = new Joker<int>(5); int foo = from a in oof select a; 

If duck printing is how query syntax works, how obvious is it, where can the official (MSDN) documentation about it be? Or any reasonable documentation?

0
source share
2 answers

In C #, there are several functions that the compiler performs structural type matching, rather than a nominal type mapping. Examples include a foreach , query understanding syntax ( select , where , etc.) and await / async . For all these functions, the compiler is actually looking for methods with specific names, and not with specific interfaces or classes.

The reason these functions are not tied to specific interfaces is to separate the language from the .NET platform implementation as much as possible. I suppose this will be considered a form of duck typing.

Eric Lippert explains this feature and argues in much more detail here .

I noticed that the documentation

+7
source

What you are missing is that List<T> implements IEnumerable<T> . Thus, "I have always believed that this syntax is limited to IEnumerable," is technically true, albeit in a limited way. IQueryable implements IEnumerable , as well as IList and arrays. This way you can execute linq queries against anything that implements IEnumerable .

Since Joker<> does not implement IEnumerable<> , your query attempt fails. Extension methods Select<>() , Where<>() , etc. Built around IEnumerable<> . So, if you want to choose from oof , you just need to update your definition of Joker<>

 public class Joker<T> : IEnumerable<T> { // (actually implement IEnumerable<T> functionality } 

(Editing: the answer really made sense in the context of the originally asked question. The edited question makes my answer obsolete)

+4
source

Source: https://habr.com/ru/post/1495331/


All Articles