Why is the method not called?

Just trying to figure it out better. I know this is due to defective execution

But what does this cause the method to not receive calls immediately. This is from EduLinq from JonSkeet.

public static partial class Enumerable { public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } foreach (TSource item in source) { if (predicate(item)) { yield return item; } } } } 

This is where I use it.

 List<int> list = new List<int>() { 1, 3, 4, 2, 8, 1 }; var s = list.Where(x => x > 4); var result = s.ToList(); 

My question, although Where is the static method in IEnumerable, is why it is not being called in list.where (). But it is called s.ToList ().

I have a breakpoint on Enumerable.Where (), it does not fall on s = list.Where(x => x > 4) , but a breakpoint falls on s.ToList()

After I saw a comment from YUCK Why does LINQ have deferred execution? I add this to the question.

Please let me know.

+4
source share
3 answers

The Where method is actually called, but it returns an IEnumerable<T> . This return value is actually a class that the compiler implements for you.

Please note that an iterator is used in your implementation (it includes a return on profitability ...). When this happens, the compiler changes your method so that it creates a class generated by the compiler, and since you are actually iterating through IEnumerable<T> , the code you wrote is executed.

The first call to MoveNext will execute the code until your first yield return . The second call will go to the next, etc.

The call to ToList() enumerated through the entire IEnumerable<T> , which, in turn, executes your entire method.

Also - ToList() does not require your code to execute here. You can use foreach loop:

 foreach(var val in s) { // Do something... } 

Or even make calls manually:

 IEnumerable<int> s = list.Where(x => x > 4); IEnumerator<int> sEnumerator = s.GetEnumerator(); // Get the enumerator // This section will cause your code to run, but only until the *first* yield statement... if (sEnumerator.MoveNext()) { int val = sEnumerator.Current(); } // Without further MoveNext() calls, you won't "finish" the foreach loop... // This block will do one more "loop" in your foreach, going until the next "yield" (or the end of the method) if (sEnumerator.MoveNext()) { int val = sEnumerator.Current(); } 
+7
source

LINQ uses deferred execution, the method will be called when you really request data.

If you use ToList (), you immediately request data by listing the list right away.

0
source

You answered your question - due to deferred execution (kind). Where called is the filtering itself, deferred.

List.Where does not return a filtered list. It returns an IEnumerable<int> , which, when retried, filters the list. Your .ToList() call .ToList() , resulting in a filter.

0
source

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


All Articles