Programing

C # 다차원 배열이 IEnumerable을 구현하지 않는 이유

lottogame 2020. 11. 22. 18:51
반응형

C # 다차원 배열이 IEnumerable을 구현하지 않는 이유?


방금 C #의 다차원 배열이 구현하지 않는 IEnumerable<T>반면 IEnumerable. 1 차원 배열의 경우 IEnumerable<T>둘 다 IEnumerable구현됩니다.

이 차이가 왜? 다차원 배열이 IEnumerable이면 반드시 일반 버전도 구현해야합니까? 다차원 배열에서 확장 메서드를 사용하려고했기 때문에 이것을 발견했습니다. 사용하지 않으면 실패합니다 Cast<T>. 그래서 다차원 배열을 구현하기위한 인수를 확실히 볼 수 있습니다 IEnumerable<T>.

코드에서 내 질문에 명확히하려면, 다음 코드 인쇄 기대 true, 네 번을 실제로 인쇄하는 동안 true, false, true, true:

int[] singleDimensionArray = new int[10];
int[,] multiDimensional = new int[10, 10];

Debug.WriteLine(singleDimensionArray is IEnumerable<int>);
Debug.WriteLine(multiDimensional is IEnumerable<int>);
Debug.WriteLine(singleDimensionArray is IEnumerable);
Debug.WriteLine(multiDimensional is IEnumerable);

CLR에는 하한이 0 인 1 차원이 보장되는 벡터 와 0이 아닌 경계와 0이 아닌 순위를 가질 수있는보다 일반적인 배열의 두 가지 다른 종류의 배열 이 있습니다.

CLI 사양의 섹션 8.9.1에서 :

또한 요소 유형이 T 인 생성 된 벡터는 인터페이스 System.Collections.Generic.IList<U>(§8.7)를 구현합니다 . 여기서 U : = T입니다.

나는 그것이 나에게 꽤 이상해 보인다고 말해야한다. 이미 구현되어 있으므로 구현 IEnumerable하지 않아야하는 이유를 알 수 없습니다 IEnumerable<T>. 을 구현하는 것은별로 의미가 IList<T>없지만 간단한 일반 인터페이스는 괜찮습니다.

원하는 경우 호출 Cast<T>(.NET 3.5를 사용하는 경우)하거나 자체 메서드를 작성하여 배열을 반복 할 수 있습니다. 캐스팅을 피하려면 각 차원의 하한 / 상한을 찾아서 가져 오는 방법을 직접 작성해야합니다. 별로 즐겁지 않습니다.


해결 방법이 있습니다. 모든 다차원 배열을 IEnumerable로 변환 할 수 있습니다.

public static class ArrayExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this Array target)
    {
        foreach (var item in target)
            yield return (T)item;
    }
}

다차원 배열은 상속 계층을위한 배열이 아닙니다 . 완전히 분리 된 유형입니다. 또한이 유형은 다음 두 가지 이유로 프레임 워크에서 좋은 지원을받지 못합니다.

  • 그다지 유용하지 않습니다. 다차원 배열의 유일한 실제 용도는 행렬입니다. 거의 모든 것에는 다른 데이터 구조 (예 : 들쭉날쭉 한 배열)가 더 적합합니다.
  • 이러한 구조에 대해 일반적이고 유용한 방법을 고안하는 것은 쉬운 일이 아닙니다.

의 경우 IEnumerable어떻게 구현되어야하나요? 즉, 요소가 어떤 순서로 열거되어야합니까? 다차원 배열에는 내재 된 순서가 없습니다.


제로 바운드 단일 차원 배열은 IEnumerable및을 모두 구현 IEnumerable<T>하지만 다차원 배열은 불행히도 IEnumerable. @Jader Dias의 "해결 방법"은 실제로 다차원 배열을로 변환 IEnumerable<T>하지만 막대한 비용이 발생합니다. 배열의 모든 요소가 상자에 들어갑니다.

다음은 모든 요소에 대해 권투를 일으키지 않는 버전입니다.

public static class ArrayExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this T[,] target)
    {
        foreach (var item in target)
            yield return item;
    }
}

들쭉날쭉 한 배열은 IEnumerable<int>둘 다 지원하지 않습니다. 다차원 구조는 실제로 유형의 배열이 아니기 때문에 유형의 배열의 배열입니다.

int[] singleDimensionArray = new int[10];
int[][] multiJagged = new int[10][];

Debug.WriteLine(singleDimensionArray is IEnumerable<int>);
Debug.WriteLine(multiJagged is IEnumerable<int[]>);
Debug.WriteLine(singleDimensionArray is IEnumerable);
Debug.WriteLine(multiJagged is IEnumerable);

Prints true, true, true, true.

Note: int[,] isn't an IEnumerable<int[]>, that's for the reasons specified in the other answer, namely there's no generic way to know which dimension to iterate over. With jagged arrays, there isn't as much room for interpretation because the syntax is pretty clear about it being an array of arrays.


Think inversely. The 2d array already exists. Just enumerate it. Create a 2d array with score and place of an initial array or marks, including duplicate values.

int[] secondmarks = {20, 15, 31, 34, 35, 50, 40, 90, 99, 100, 20};

IEnumerable<int> finallist = secondmarks.OrderByDescending(c => c);

int[,] orderedMarks = new int[2, finallist.Count()];

Enumerable.Range(0, finallist.Count()).ToList().ForEach(k => {orderedMarks[0, k] = (int) finallist.Skip(k).Take(1).Average();
orderedMarks[1, k] = k + 1;}); 

Enumerable.Range(0, finallist.Count()).Select(m => new {Score = orderedMarks[0, m], Place = orderedMarks[1, m]}).Dump();

Results:

Score Place

100     1
99      2 
90      3 
50      4 
40      5 
35      6    
34      7    
31      8    
20      9     
20     10 
15     11 

참고URL : https://stackoverflow.com/questions/275073/why-do-c-sharp-multidimensional-arrays-not-implement-ienumerablet

반응형