我该如何摆脱这个goto?
How do I get rid of this goto?
我刚刚开始一个职位,在工作日结束时,我通过慢慢阅读我们的代码库来等待流量。我遇到了这一点,即使在白板上花了相当长的时间后,我仍然想不出提取 goto
的方法。有没有办法消除这种跳跃?
public void MyUpdate(MyType foo)
{
/*Prep code for the loops*/
foreach (Thing bar in something)
{
foreach (Collection item in bar.Stuff)
{
Data dataRX = item.First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
goto exitLoops;
}
}
}
exitLoops: ;
}
将内部循环移动到一个方法,并根据其 return 值有条件地中断。
这不是很好,但如果不实施全新的算法,这似乎是最简单的方法:
foreach (Thing bar in something)
{
bool exitLoop = false;
foreach (Collection item in bar.Stuff)
{
Data dataRX = item.First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
exitLoop = true;
break;
}
}
if (exitLoop) break;
}
既然标签exitLoops
在方法的最后,那么你可以简单地使用return
退出方法,像这样:
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
return;
}
另一种方法是使用这样的标志:
bool done = false;
foreach (Thing bar in something)
{
foreach (Collection item in bar.Stuff)
{
Data dataRX = item.First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
done = true;
break;
}
}
if(done)
break;
}
即使标签后面有一些代码,您也可以使用第二种方法。
或者,您可以使用 LINQ 执行此操作:
public void MyUpdate(MyType foo)
{
Thing dummy = something.FirstOrDefault(bar => bar.Stuff.SkipWhile((item) =>
{
Data dataRx = item.First;
if (dataRx != null && dataRx.ID.Equals(globalNonsense.ID))
{
dataRx.fooBuddy = foo;
return false;
}
else
{
return true;
}
}).Count() != 0);
}
如果您使用 foreach
,则需要 break
或 return
。但如果没有 break
、return
或 goto
,则有此选项:
public void MyUpdate(MyType foo)
{
bool stop = false;
/*Prep code for the loops*/
for (var i = 0; !stop && (i < something.Count); i++)
{
for (var j = 0; !stop && (j < something[i].Stuff.Count); j++)
{
Data dataRX = something[i].Stuff[j].First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
stop = true;
}
}
}
}
我刚刚开始一个职位,在工作日结束时,我通过慢慢阅读我们的代码库来等待流量。我遇到了这一点,即使在白板上花了相当长的时间后,我仍然想不出提取 goto
的方法。有没有办法消除这种跳跃?
public void MyUpdate(MyType foo)
{
/*Prep code for the loops*/
foreach (Thing bar in something)
{
foreach (Collection item in bar.Stuff)
{
Data dataRX = item.First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
goto exitLoops;
}
}
}
exitLoops: ;
}
将内部循环移动到一个方法,并根据其 return 值有条件地中断。
这不是很好,但如果不实施全新的算法,这似乎是最简单的方法:
foreach (Thing bar in something)
{
bool exitLoop = false;
foreach (Collection item in bar.Stuff)
{
Data dataRX = item.First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
exitLoop = true;
break;
}
}
if (exitLoop) break;
}
既然标签exitLoops
在方法的最后,那么你可以简单地使用return
退出方法,像这样:
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
return;
}
另一种方法是使用这样的标志:
bool done = false;
foreach (Thing bar in something)
{
foreach (Collection item in bar.Stuff)
{
Data dataRX = item.First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
done = true;
break;
}
}
if(done)
break;
}
即使标签后面有一些代码,您也可以使用第二种方法。
或者,您可以使用 LINQ 执行此操作:
public void MyUpdate(MyType foo)
{
Thing dummy = something.FirstOrDefault(bar => bar.Stuff.SkipWhile((item) =>
{
Data dataRx = item.First;
if (dataRx != null && dataRx.ID.Equals(globalNonsense.ID))
{
dataRx.fooBuddy = foo;
return false;
}
else
{
return true;
}
}).Count() != 0);
}
如果您使用 foreach
,则需要 break
或 return
。但如果没有 break
、return
或 goto
,则有此选项:
public void MyUpdate(MyType foo)
{
bool stop = false;
/*Prep code for the loops*/
for (var i = 0; !stop && (i < something.Count); i++)
{
for (var j = 0; !stop && (j < something[i].Stuff.Count); j++)
{
Data dataRX = something[i].Stuff[j].First;
if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
// Update Data with the latest changes
dataRX.fooBuddy = foo;
stop = true;
}
}
}
}