C# 是否有必要在循环后调用'yield break'?
在我的代码中,我有这样一个方法C# 是否有必要在循环后调用'yield break'?,c#,C#,在我的代码中,我有这样一个方法 public static IEnumerable<int> GetDiff(int start, int end) { while (start < end) { yield return start; start++; } yield break; // do we need to call it explicitly? } 公共静态IEnumerable GetDif
public static IEnumerable<int> GetDiff(int start, int end)
{
while (start < end)
{
yield return start;
start++;
}
yield break; // do we need to call it explicitly?
}
公共静态IEnumerable GetDiff(int-start,int-end)
{
while(开始<结束)
{
收益率-收益率开始;
启动++;
}
yield break;//我们需要显式地调用它吗?
}
因此,我感兴趣的测试用例是
GetDiff(1,5)
和GetDiff(5,1)
。虽然很清楚第一种情况下会发生什么,但不太清楚如何在第二种情况下完成而不出现收益率中断代码>循环后否这不是必需的。它将在以下方面发挥作用:
public static IEnumerable<int> GetDiff(int start, int end)
{
while (start < end)
{
yield return start;
start++;
}
// yield break; - It is not necessary. It is like `return` which does not return a value.
}
公共静态IEnumerable GetDiff(int-start,int-end)
{
while(开始<结束)
{
收益率-收益率开始;
启动++;
}
//屈服断裂;-这是不必要的。它就像不返回值的“return”。
}
在这种情况下,函数的执行只需退出即可结束
但你可以这样写:
public static IEnumerable<int> GetDiff(int start, int end)
{
while (true)
{
if (start >= end)
yield break;
yield return start;
start++;
}
Console.WriteLine("Finish"); // note that this line will not be executed
}
// <GetDiff>d__1
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
[CompilerGenerated]
private sealed class <GetDiff>d__1 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IDisposable, IEnumerator
{
private int <>1__state;
private int <>2__current;
private int <>l__initialThreadId;
private int start;
public int <>3__start;
private int end;
public int <>3__end;
int IEnumerator<int>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <GetDiff>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
break;
case 1:
<>1__state = -1;
start++;
break;
}
if (start < end)
{
<>2__current = start;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
<GetDiff>d__1 <GetDiff>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<GetDiff>d__ = this;
}
else
{
<GetDiff>d__ = new <GetDiff>d__1(0);
}
<GetDiff>d__.start = <>3__start;
<GetDiff>d__.end = <>3__end;
return <GetDiff>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator();
}
}
公共静态IEnumerable GetDiff(int-start,int-end)
{
while(true)
{
如果(开始>=结束)
屈服断裂;
收益率-收益率开始;
启动++;
}
Console.WriteLine(“Finish”);//注意这一行不会被执行
}
将您的代码放入编译器中,构建并反向工程回C#,结果如下:
using System.Collections.Generic;
public static IEnumerable<int> GetDiff(int start, int end)
{
while (start < end)
{
yield return start;
start++;
}
}
类d_u1
如下所示:
public static IEnumerable<int> GetDiff(int start, int end)
{
while (true)
{
if (start >= end)
yield break;
yield return start;
start++;
}
Console.WriteLine("Finish"); // note that this line will not be executed
}
// <GetDiff>d__1
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
[CompilerGenerated]
private sealed class <GetDiff>d__1 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IDisposable, IEnumerator
{
private int <>1__state;
private int <>2__current;
private int <>l__initialThreadId;
private int start;
public int <>3__start;
private int end;
public int <>3__end;
int IEnumerator<int>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <GetDiff>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
break;
case 1:
<>1__state = -1;
start++;
break;
}
if (start < end)
{
<>2__current = start;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
<GetDiff>d__1 <GetDiff>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<GetDiff>d__ = this;
}
else
{
<GetDiff>d__ = new <GetDiff>d__1(0);
}
<GetDiff>d__.start = <>3__start;
<GetDiff>d__.end = <>3__end;
return <GetDiff>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator();
}
}
它正在检查使用者是否是同一个线程,并且状态没有改变(从原始的-2
),如果保持不变,它将返回自身。否则,它将返回一个克隆。这意味着,如果从另一个线程调用GetEnumerator
,或者在迭代开始后由同一个线程调用,则返回的IEnumerator
将从一开始就启动(应该如此)
还要注意,GetEnumerator
将状态更改为0
。这很重要
现在,请注意MoveNext
方法。它是与您的代码等效的状态机:
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
break;
case 1:
<>1__state = -1;
start++;
break;
}
if (start < end)
{
<>2__current = start;
<>1__state = 1;
return true;
}
return false;
}
那么,的收益率是多少代码>做什么?在这种情况下,什么都没有<代码>屈服断裂
用于指示状态机应该结束(MoveNext
返回false
),但是状态机无论如何都会在那里结束,因为它是方法的结束。因此,您只会发现屈服断裂代码>当它不在方法末尾时有用(且有意义)。例如,请参见
此外,我还认为添加会产生中断代码>对代码的可维护性或可读性没有帮助。没有。谁教你的?“如何完成”是什么意思?它只是到达过程的末尾。屈服中断就像一个线程到达其函数的末尾并终止。@Frenchy,嗯<代码>屈服断裂代码>就像是中断代码>在for
循环中。@john,当你使用收益率时,你使用的生成器将永远不会停止。停止发电机。。而且不会返回值…但这不是必需的…谢谢,回答得很好!因此编译器为您返回MoveNext=false
,我们不需要在方法末尾显式地产生break
[DebuggerHidden]
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
<GetDiff>d__1 <GetDiff>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<GetDiff>d__ = this;
}
else
{
<GetDiff>d__ = new <GetDiff>d__1(0);
}
<GetDiff>d__.start = <>3__start;
<GetDiff>d__.end = <>3__end;
return <GetDiff>d__;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
break;
case 1:
<>1__state = -1;
start++;
break;
}
if (start < end)
{
<>2__current = start;
<>1__state = 1;
return true;
}
return false;
}
{
E e = ((C)(x)).GetEnumerator();
try {
while (e.MoveNext()) {
V v = (V)(T)e.Current;
embedded_statement
}
}
finally {
... // Dispose e
}
}