자세 한 설명 c \ # 교체 기
. NET 에서 교체 기 모드 는 IEnumerator 와 IEnumerable 및 이에 대응 하 는 범용 인터페이스 에 의 해 봉 인 됩 니 다.하나의 클래스 가 IEnumerable 인 터 페 이 스 를 실현 하면 교체 할 수 있 습 니 다.GetEnumerator 방법 을 호출 하면 IEnumerator 인터페이스의 실현 을 되 돌려 줍 니 다. 이것 이 바로 교체 기 자체 입 니 다.교체 기 는 데이터베이스 에 있 는 커서 와 유사 하 며, 그 는 데이터 시퀀스 의 위치 기록 이다.교체 기 는 앞으로 만 이동 할 수 있 고 같은 데이터 시퀀스 에서 여러 개의 교체 기 가 동시에 데 이 터 를 조작 할 수 있다.
C \ # 1 에 교체 기 에 대한 지원 이 내장 되 어 있 습 니 다. 그것 이 바로 foreach 문 입 니 다.for 순환 구문 보다 직접적 이 고 간단 한 집합 교 체 를 할 수 있 도록 컴 파일 러 는 foreach 를 컴 파일 하여 GetEnumerator 와 MoveNext 방법 과 Current 속성 을 호출 합 니 다. 대상 이 IDisposable 인 터 페 이 스 를 실현 하면 교체 가 완 료 된 후에 교체 기 를 방출 합 니 다.그러나 C \ # 1 에서 하나의 교체 기 를 실현 하 는 것 은 상대 적 으로 좀 번 거 로 운 조작 이다.C \ # 2 는 이 일 을 크게 간단 하 게 만 들 었 고 교체 기 를 실현 하 는 많은 일 을 절약 했다.
다음은 하나의 교체 기와 C \ # 2 가 교체 기 실현 에 대한 간 화 를 어떻게 실현 하 는 지 살 펴 본 다음 에 몇 개의 교체 기 가 현실 생활 에서 의 예 를 들 어 보 자.
1. C \ # 1: 교체 기의 번 거 로 움 을 수 동 으로 실현
만약 우리 가 링 버퍼 에 기반 한 새로운 집합 유형 을 실현 해 야 한다 고 가정 합 니 다.저 희 는 IEnumerable 인 터 페 이 스 를 실현 하여 사용자 가 이 집합 중의 모든 요 소 를 쉽게 이용 할 수 있 도록 할 것 입 니 다.우 리 는 다른 세부 사항 을 무시 하고 교체 기 를 어떻게 실현 하 는 지 에 만 집중 했다.집합 은 값 을 배열 에 저장 하고 집합 은 교체 의 시작 점 을 설정 할 수 있다. 예 를 들 어 집합 에 5 개의 요소 가 있다 고 가정 하면 시작 점 을 2 로 설정 할 수 있다. 그러면 교체 출력 은 2, 3, 4, 0 이 고 마지막 은 1 이다. 간단하게 보 여줄 수 있 도록 우 리 는 설정 값 과 시작 점 의 구조 함 수 를 제공 했다.우 리 는 다음 과 같은 방식 으로 집합 을 옮 겨 다 닐 수 있 게 한다.
object[] values = { "a", "b", "c", "d", "e" };
IterationSample collection = new IterationSample(values, 3);
foreach (object x in collection)
{
Console.WriteLine(x);
}
시작 점 을 3 으로 설정 하기 때문에 집합 출력 결 과 는 d, e, a, b 및 c 입 니 다. 현재 Iteration Sample 류 의 교체 기 를 어떻게 실현 하 는 지 살 펴 보 겠 습 니 다.
class IterationSample : IEnumerable
{
Object[] values;
Int32 startingPoint;
public IterationSample(Object[] values, Int32 startingPoint)
{
this.values = values;
this.startingPoint = startingPoint;
}
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
우 리 는 아직 GetEnumerator 방법 을 실현 하지 못 했 습 니 다. 그러나 GetEnumerator 부분의 논 리 를 어떻게 씁 니까? 첫째, 커서 의 현재 상 태 를 어 딘 가 에 존재 하 는 것 입 니 다.한편, 교체 기 모드 는 한 번 에 모든 데 이 터 를 되 돌려 주 는 것 이 아니 라 클 라 이언 트 가 한 번 에 한 데이터 만 요청 하 는 것 입 니 다.이것 은 우리 가 고객 이 현재 집합 에 요청 한 기록 을 기록 해 야 한 다 는 것 을 의미한다.C \ # 2 컴 파 일 러 는 교체 기의 상태 저장 에 많은 일 을 해 주 었 습 니 다.이제 어떤 상태 와 상태 가 어디 에 존재 하 는 지 살 펴 보 겠 습 니 다. Iteration Sample 집합 에 상 태 를 저장 하여 IEnumerator 와 IEnumerable 방법 을 실현 하려 고 합 니 다.어떻게 보면 가능 할 것 같 습 니 다. 왜냐하면 데 이 터 는 정확 한 곳 에 있 고 시작 위 치 를 포함 합 니 다.우리 의 GetEnumerator 방법 은 this 만 되 돌려 줍 니 다.그러나 이 방법 은 GetEnumerator 방법 이 여러 번 호출 되면 여러 개의 독립 된 교체 기 가 되 돌아 오 는 중요 한 문제 가 있다.예 를 들 어, 우 리 는 두 개의 포 레 치 문 구 를 사용 하여 가능 한 모든 값 을 얻 을 수 있다.이 두 개의 교 체 는 서로 독립 해 야 한다.이것 은 우리 가 GetEnumerator 를 호출 할 때마다 돌아 오 는 두 개의 교체 기 대상 이 독립 해 야 한 다 는 것 을 의미한다.우 리 는 여전히 Iteration Sample 류 에서 해당 함 수 를 통 해 직접 실현 할 수 있다.그러나 우리 류 는 여러 가지 직책 을 가지 고 있 고 이 분 은 단일 직책 원칙 을 외 웠 다.따라서 교체 기 자 체 를 실현 하기 위해 다른 종 류 를 만 듭 니 다.우 리 는 C \ # 의 내부 클래스 를 사용 하여 이 논 리 를 실현 한다.코드 는 다음 과 같 습 니 다:
class IterationSampleEnumerator : IEnumerator
{
IterationSample parent;// #1
Int32 position;// #2
internal IterationSampleEnumerator(IterationSample parent)
{
this.parent = parent;
position = -1;// 0 , -1, , #3
}
public bool MoveNext()
{
if (position != parent.values.Length) // , #4
{
position++;
}
return position < parent.values.Length;
}
public object Current
{
get
{
if (position == -1 || position == parent.values.Length)// #5
{
throw new InvalidOperationException();
}
Int32 index = position + parent.startingPoint;// #6
index = index % parent.values.Length;
return parent.values[index];
}
}
public void Reset()
{
position = -1;// -1 #7
}
} 간단 한 교체 기 를 실현 하려 면 이렇게 많은 코드 를 수 동 으로 써 야 합 니 다.
public IEnumerator GetEnumerator()
{
return new IterationSampleEnumerator(this);
}
2. C \ # 2: yield 문 구 를 통 해 교체 간소화
C \ # 2 는 교 체 를 더욱 간단하게 만 들 었 다. 코드 의 양 을 많이 줄 였 고 코드 도 더욱 우아 하 게 만 들 었 다.다음 코드 는 재 C \ # 2 에서 GetEnumerator 방법 을 실현 하 는 전체 코드 를 보 여 줍 니 다.
public IEnumerator GetEnumerator()
{
for (int index = 0; index < this.values.Length; index++)
{
yield return values[(index + startingPoint) % values.Length];
}
}
간단 한 몇 줄 코드 만으로 도 Iteration SampleIterator 류 에 필요 한 기능 을 완전히 실현 할 수 있 습 니 다.방법 은 매우 평범 해 보이 는데, yield return 을 사용 한 것 을 제외 하고.이 문 구 는 컴 파일 러 에 게 이것 은 일반적인 방법 이 아니 라 실행 해 야 할 교체 블록 (yield block) 이 라 고 알려 줍 니 다. 그 는 IEnumerator 대상 을 되 돌려 줍 니 다. 교체 블록 을 사용 하여 교체 방법 을 실행 하고 IEnumerable 이 실현 해 야 할 유형, IEnumerator 또는 대응 하 는 범 형 을 되 돌려 줄 수 있 습 니 다.만약 에 비 일반적인 버 전의 인터페이스 가 실현 된다 면 교체 블록 이 돌아 오 는 yield type 은 Object 형식 이 고 그렇지 않 으 면 해당 하 는 일반적인 유형 으로 돌아 갑 니 다.예 를 들 어 IEnumerable 인 터 페 이 스 를 실현 하 는 방법 이 있다 면 yield 가 돌아 오 는 유형 은 String 형식 입 니 다.교체 블록 에 서 는 yield return 을 제외 하고 일반적인 return 문 구 를 사용 할 수 없습니다.블록 에 있 는 모든 yield return 문 구 는 블록의 마지막 반환 형식 과 호 환 되 는 형식 을 되 돌려 야 합 니 다.예 를 들 어 방법 정의 가 IEnumeratble 형식 으로 돌아 가 야 한다 면 yield return 1 을 사용 할 수 없습니다.강조해 야 할 것 은 교체 블록 에 대해 우리 가 쓴 방법 은 순서대로 실행 하 는 것 처럼 보이 지만 사실은 컴 파일 러 에 게 상태 기 를 만들어 달라 고 한 것 이다.이것 이 바로 C \ # 1 에서 우리 가 쓴 부분 코드 입 니 다. 호출 자 는 호출 할 때마다 하나의 값 만 되 돌려 야 하기 때문에 마지막 반환 값 을 기억 해 야 합 니 다. 집합 에서 위 치 를 기억 해 야 합 니 다.컴 파일 러 가 교체 블록 을 만 났 을 때 상태 기 를 실현 하 는 내부 클래스 를 만 들 었 습 니 다.이 종 류 는 매개 변 수 를 포함 하여 우리 교체 기의 정확 한 현재 위치 와 로 컬 변 수 를 기억 합 니 다.이 종 류 는 우리 가 이전에 손 으로 쓴 코드 와 약간 유사 하 다. 그 는 기록 해 야 할 모든 상 태 를 인 스 턴 스 변수 로 저장 했다.다음은 교체 기 를 실현 하기 위해 이 상태 기 는 순서대로 실행 해 야 하 는 조작 을 살 펴 보 자.
초기 상태 가 필요 합 니 다.
2.2 교체 기의 실행 절차
다음 코드 는 교체 기의 실행 절 차 를 보 여 주 었 고 코드 출력 (0, 1, 2, - 1) 을 보 여 주 며 종료 합 니 다.
class Program {
static readonly String Padding = new String(' ', 30);
static IEnumerable<int32> CreateEnumerable()
{
Console.WriteLine("{0} CreateEnumerable() ", Padding);
for (int i = 0; i < 3; i++)
{
Console.WriteLine("{0} yield {1}", i);
yield return i;
Console.WriteLine("{0}yield ", Padding);
}
Console.WriteLine("{0} Yielding ", Padding);
yield return -1;
Console.WriteLine("{0} CreateEnumerable() ", Padding);
}
static void Main(string[] args)
{
IEnumerable<int32> iterable = CreateEnumerable();
IEnumerator<int32> iterator = iterable.GetEnumerator();
Console.WriteLine(" ");
while (true)
{
Console.WriteLine(" MoveNext ……");
Boolean result = iterator.MoveNext();
Console.WriteLine("MoveNext {0}", result);
if (!result)
{
break;
}
Console.WriteLine(" ……");
Console.WriteLine(" {0}", iterator.Current);
}
Console.ReadKey();
}
}
출력 결과 에서 몇 가 지 를 볼 수 있 습 니 다.
2.3 교체 기의 특수 집행 절차
일반적인 방법 에서 return 문 구 는 보통 두 가지 역할 을 하 는데 하 나 는 호출 자가 실행 한 결 과 를 되 돌려 주 는 것 이다.둘째, 종료 방법의 집행, 종료 전에 finally 문 구 를 실행 하 는 방법 입 니 다.위의 예 에서 우 리 는 yield return 문 구 는 짧 은 종료 방법 일 뿐 MoveNext 가 다시 호출 될 때 계속 실행 하 는 것 을 보 았 다.여기 서 우 리 는 finally 문장 블록 을 쓰 지 않 았 다.어떻게 진정한 종료 방법, 종료 방법 시 finnally 구문 블록 이 어떻게 실행 되 는 지, 다음은 비교적 간단 한 구 조 를 살 펴 보 겠 습 니 다: yield break 구문 블록.yield break 를 사용 하여 교체 종료
static IEnumerable<int32> CountWithTimeLimit(DateTime limit)
{
try
{
for (int i = 1; i <= 100; i++)
{
if (DateTime.Now >= limit)
{
yield break;
}
yield return i;
}
}
finally
{
Console.WriteLine(" !"); Console.ReadKey();
}
}
static void Main(string[] args)
{
DateTime stop = DateTime.Now.AddSeconds(2);
foreach (Int32 i in CountWithTimeLimit(stop))
{
Console.WriteLine(" {0}", i);
Thread.Sleep(300);
}
}
Asp. Net 고급 기술 군 89336052
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.