Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 收益返回和异常处理_C#_Exception_Clr_Jit_Yield Return - Fatal编程技术网

C# 收益返回和异常处理

C# 收益返回和异常处理,c#,exception,clr,jit,yield-return,C#,Exception,Clr,Jit,Yield Return,我刚刚遇到了一个案例,使用收益率返回的方法没有抛出我预期的ArgumentException。我在这里用最简单的类重新构建了这个案例: class Program { static void Main(string[] args) { try { var listA = FooA(count: 0); Console.WriteLine("A did not throw exception!");

我刚刚遇到了一个案例,使用收益率返回的方法没有抛出我预期的ArgumentException。我在这里用最简单的类重新构建了这个案例:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            var listA = FooA(count: 0);
            Console.WriteLine("A did not throw exception!");
        }
        catch (ArgumentException)
        {
            Console.WriteLine("A threw exception!");
        }

        try
        {
            var listB = FooB(count: 0);
            Console.WriteLine("B did not throw exception!");
        }
        catch (ArgumentException)
        {
            Console.WriteLine("B threw exception!");
        }

        Console.ReadLine();
    }

    private static IEnumerable<int> FooA(int count)
    {
        if(count == 0)
            throw new ArgumentException("Count must be above 0");
        var list = new List<int>();
        for (var i = 0; i < count; i++)
        {
            list.Add(i);
        }
        return list;
    }

    private static IEnumerable<int> FooB(int count)
    {
        if (count == 0)
            throw new ArgumentException("Count must be above 0");
        for (var i = 0; i < count; i++)
        {
            yield return i;
        }
    }
}

有人能给我解释一下为什么FooB不抛出异常而FooA抛出异常吗?

这是因为
FooB
从未被计算过

当您调用一个方法时,会立即调用该方法。当您使用
yield
并返回一个可枚举项时,仅当某些内容需要使用返回的值时才会调用该方法,并且一次只调用一个项;这是
收益率的好处

因此,如果您添加使用该值的内容

try
{
    var listB = FooB(count: 0);
    Console.WriteLine(listB.First()); // use the IEnumerable returned
    Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
    Console.WriteLine("B threw exception!");
}

你会看到你预期的结果

你有更多的信息吗?在你开始迭代之前,FooB不会抛出异常。这是一个常见的陷阱。这是因为
收益率回报率
。它会将该方法转换为类。通常,您会将yield方法的实现拆分为单独的私有方法,以便在调用站点进行错误处理。因为从未调用FooB()。这很有意义,谢谢。
try
{
    var listB = FooB(count: 0);
    Console.WriteLine(listB.First()); // use the IEnumerable returned
    Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
    Console.WriteLine("B threw exception!");
}