为什么没有调用该方法? [英] Why is the method not getting called?

查看:53
本文介绍了为什么没有调用该方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是想更好地理解这一点.我知道这是由于延期执行

Just trying to understand this better. I know this is because of Deffered Execution

但这是什么导致该方法没有立即被调用.这是来自JonSkeet的EduLinq.

But what is it causing the method not getting called 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 am using it.

List<int> list = new List<int>() { 1, 3, 4, 2, 8, 1 };

var s = list.Where(x => x > 4);

var result = s.ToList();

我的问题是,虽然 Where 是IEnumerable上的静态方法,但为什么没有在list.where()上调用它.但这是在s.ToList()上调用的.

My question is though Where is a static method on IEnumerable why is it not called on list.where(). But it is called on s.ToList().

我在Enumerable上有一个断点.where()在 s = list上没有命中.在哪里(x => x> 4)但在 s上有断点.ToList()

I have a breakpoint on Enumerable.Where() it is not hit on s = list.Where(x => x > 4) but the breakpoint is hit on s.ToList()

当我看到 YUCK 为什么LINQ为什么推迟执行?的评论之后,我将其添加到问题中.

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

请让我知道.

推荐答案

实际上调用了 Where 方法,但它返回了 IEnumerable< T> .该返回值实际上是编译器为您实现的类.

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

请注意,您的实现使用了 iterator (包括yield return ...).发生这种情况时,编译器会改变您的方法,从而创建一个由编译器生成的类,并在您实际迭代时通过 IEnumerable< T> 写被执行.

Note that your implementation uses an iterator (it includes yield return ...). When this occurs, the compiler changes your method around so that it creates a compiler-generated class, and, as you actually iterate through the IEnumerable<T>, the code you wrote gets executed.

第一次调用 MoveNext 时,将执行直到您的第一次 yield return 的代码.第二个呼叫将一直持续到下一个,依此类推.

The first time MoveNext is called, the code up to your first yield return will get executed. The second call will go until the next, etc.

调用 ToList()会枚举整个 IEnumerable< T> ,这反过来会执行您的整个方法.

Calling ToList() enumerates through the entire IEnumerable<T>, which in turn executes your entire method.

也-在这里不需要 ToList()来执行代码.您可以使用foreach循环:

Also - ToList() isn't required here to have your code execute. You could use a foreach loop:

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

或者甚至手动执行呼叫:

Or even execute the 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();
}

这篇关于为什么没有调用该方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆