真的有一个有效的代码路径,这个函数不会 return 一个值吗?
Is there really a valid code-path where this function won't return a value?
我有以下函数,它遍历工作人员列表,调用他们的 DoStuff() 方法。如果第一个工人失败,我会尝试下一个,直到我没有工人。如果都失败了,我重新抛出最后一个异常。
// workers is an IList<>.
public object TryDoStuff()
{
for (int i = 0; i < workers.Count; i++)
{
try
{
return worker[i].DoStuff();
}
catch
{
if (i == workers.Count - 1)
{
throw; // This preserves the stack trace
}
else
{
continue; // Try the next worker
}
}
}
}
在编译时,我得到一个错误 "not all code paths return a value" 这个函数。虽然我可以通过在 for 循环之后添加一个显式 return 来消除错误,但我怀疑编译器在这里是否准确,因为我看不出如果没有 returning 将如何转义 for 循环或重新抛出异常。如果重新抛出异常,则 returning 值是有效的。
我错过了什么? csc 无法推理 catch 块中的条件吗?
是
如果在最后一个索引上抛出异常并且计数不是您期望的(不太可能但可能)
或者如 RAM 所指出的,如果 Count
为零
在这种情况下,静态分析和随后的编译错误是非常有道理的
如前所述,如果 workers 为空(计数为 0),则没有有效的 return 路径。
还有另一个竞争条件(显然取决于完整的上下文),其中 workers
不为空,在元素上抛出异常,workers
中仍有元素要迭代, but 在评估 if (i == workers.Count - 1)
和 之前 continue
语句执行后,另一个线程从 workers
中删除元素(或将整个 workers
变量更改为新实例)。
在那种情况下,for
条件将在下一次迭代中意外地 return 为假,并且您将退出循环,没有针对该方法的 return 语句。
public object TryDoStuff()
{
for (int i = 0; i < workers.Count; i++)
{
try
{
return worker[i].DoStuff();
}
catch
{
if (i == workers.Count - 1)
{
throw; // This preserves the stack trace
}
else
{
// XXX If workers is changed by another thread here. XXX
continue; // Try the next worker
}
}
}
}
我写了一条评论给你:
What will be happen if the count of the workers list items be
zero?
这似乎是编译器问题,它没有对您的代码进行更多研究! :)
实际上这个原因足以让编译器向您显示下面的错误
not all code paths return a value
当编译器在整个方法体中遇到循环时,它假定循环条件导致循环体被忽略,然后它也期望循环外的任何值。
是的,即使我们按照循环执行的方式设置循环条件!
证明:
错误:
public static object TryDoStuff()
{
var result =0;
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Add 100 unit");
result += 100;
return result;
}
//Console.WriteLine("last line");
// return result;
}
没有错误:
public static object TryDoStuff()
{
var result =0;
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Add 100 unit");
result += 100;
// return result; you can un-comment this line too
}
Console.WriteLine("last line");
return result;
}
我有以下函数,它遍历工作人员列表,调用他们的 DoStuff() 方法。如果第一个工人失败,我会尝试下一个,直到我没有工人。如果都失败了,我重新抛出最后一个异常。
// workers is an IList<>.
public object TryDoStuff()
{
for (int i = 0; i < workers.Count; i++)
{
try
{
return worker[i].DoStuff();
}
catch
{
if (i == workers.Count - 1)
{
throw; // This preserves the stack trace
}
else
{
continue; // Try the next worker
}
}
}
}
在编译时,我得到一个错误 "not all code paths return a value" 这个函数。虽然我可以通过在 for 循环之后添加一个显式 return 来消除错误,但我怀疑编译器在这里是否准确,因为我看不出如果没有 returning 将如何转义 for 循环或重新抛出异常。如果重新抛出异常,则 returning 值是有效的。
我错过了什么? csc 无法推理 catch 块中的条件吗?
是
如果在最后一个索引上抛出异常并且计数不是您期望的(不太可能但可能)
或者如 RAM 所指出的,如果
Count
为零
在这种情况下,静态分析和随后的编译错误是非常有道理的
如前所述,如果 workers 为空(计数为 0),则没有有效的 return 路径。
还有另一个竞争条件(显然取决于完整的上下文),其中 workers
不为空,在元素上抛出异常,workers
中仍有元素要迭代, but 在评估 if (i == workers.Count - 1)
和 之前 continue
语句执行后,另一个线程从 workers
中删除元素(或将整个 workers
变量更改为新实例)。
在那种情况下,for
条件将在下一次迭代中意外地 return 为假,并且您将退出循环,没有针对该方法的 return 语句。
public object TryDoStuff()
{
for (int i = 0; i < workers.Count; i++)
{
try
{
return worker[i].DoStuff();
}
catch
{
if (i == workers.Count - 1)
{
throw; // This preserves the stack trace
}
else
{
// XXX If workers is changed by another thread here. XXX
continue; // Try the next worker
}
}
}
}
我写了一条评论给你:
What will be happen if the count of the workers list items be zero?
这似乎是编译器问题,它没有对您的代码进行更多研究! :)
实际上这个原因足以让编译器向您显示下面的错误
not all code paths return a value
当编译器在整个方法体中遇到循环时,它假定循环条件导致循环体被忽略,然后它也期望循环外的任何值。
是的,即使我们按照循环执行的方式设置循环条件!
证明:
错误:
public static object TryDoStuff()
{
var result =0;
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Add 100 unit");
result += 100;
return result;
}
//Console.WriteLine("last line");
// return result;
}
没有错误:
public static object TryDoStuff()
{
var result =0;
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Add 100 unit");
result += 100;
// return result; you can un-comment this line too
}
Console.WriteLine("last line");
return result;
}