C# 다차원 배열이 ienumerable 를 구현하지 않는 이유는 무엇입니까?
-
07-07-2019 - |
문제
방금 C#의 다차원 배열이 구현되지 않는다는 것을 알았습니다. IEnumerable<T>
, 구현하는 동안 IEnumerable
. 단일 차원 배열의 경우 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);
진실, 진실, 진실, 진실을 인쇄합니다.
메모: int[,]
그렇지 않습니다 IEnumerable<int[]>
, 그것은 다른 답변에 명시된 이유, 즉 반복 할 차원을 알 수있는 일반적인 방법이 없습니다. 들쭉날쭉 한 배열의 경우 구문이 배열 배열이라는 것에 대해 구문이 분명하기 때문에 해석의 여지가 많지 않습니다.
반대로 생각하십시오. 2D 배열은 이미 존재합니다. 그냥 열거하십시오. 중복 값을 포함하여 초기 배열 또는 마크의 점수 및 장소가있는 2D 배열을 만듭니다.
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();
결과:
Score Place
100 1
99 2
90 3
50 4
40 5
35 6
34 7
31 8
20 9
20 10
15 11