C# 收益返回和异常处理
我刚刚遇到了一个案例,使用收益率返回的方法没有抛出我预期的ArgumentException。我在这里用最简单的类重新构建了这个案例: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!");
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!");
}