MyClass[] array;
List<MyClass> list;
하나가 다른 것보다 선호되는 시나리오는 무엇입니까? 그리고 왜?
MyClass[] array;
List<MyClass> list;
하나가 다른 것보다 선호되는 시나리오는 무엇입니까? 그리고 왜?
답변:
실제로 배열을 사용하려는 경우는 거의 없습니다. List<T>
어레이 크기 조정은 비용이 많이 들기 때문에 언제든지 데이터를 추가 / 제거 할 때 사용 하십시오. 데이터 길이가 고정되어 있다는 것을 알고 벤치마킹 후 매우 특정한 이유로 미세 최적화하려는 경우 배열이 유용 할 수 있습니다.
List<T>
LINQ는 배열보다 훨씬 더 많은 기능을 제공 하지만 거의 항상 올바른 선택입니다. params
물론 논쟁을 제외하고 . ;-피
카운터로서 List<T>
-1 차원입니다. 어디에 당신이 int[,]
or 와 같은 직사각형 (등) 배열을 가지고 string[,,]
있지만 객체 모델에서 그러한 데이터를 모델링하는 다른 방법이 있습니다 (필요한 경우).
또한보십시오:
즉, protobuf-net 프로젝트 에서 배열을 많이 사용합니다 . 전적으로 성능을 위해 :
byte[]
인코딩에는 매우 필수적입니다.byte[]
기본 스트림 (및 vv)으로 보내기 전에 채우는 로컬 롤링 버퍼를 사용합니다 . BufferedStream
등 보다 빠릅니다 .Foo[]
대신 List<Foo>
을 사용합니다.그러나 이것은 분명히 예외입니다. 일반적인 업무 처리 과정에서는 List<T>
매번 승리합니다.
실제로 놀랍게도 링크를 추가하라는 대답은 아직 언급되지 않았습니다 . "어딘가 해로운 것으로 간주되는 배열" 에 대한 Eric의 Lippert 블로그 항목 .
실용적인 곳에서는 컬렉션을 사용하는 것이 좋다고 제목에서 판단 할 수 있지만 Marc가 올바르게 지적한 것처럼 배열이 실제로 유일한 솔루션 인 곳이 많이 있습니다.
권장하는 다른 답변에도 불구하고 List<T>
처리 할 때 배열을 사용하려고합니다.
List<T>
바이트 배열이 아닌 here 을 사용하는 것에 대해 말하는 것은 무엇 입니까?
실제로 성능에 관심이 없다면 "C ++ 대신 .Net을 사용하는 이유는 무엇입니까?"라는 의미입니다. List <>를 고수해야합니다. 유지 관리가 쉽고 배열 뒤에서 배열 크기를 조정하는 모든 더러운 작업을 수행합니다. (필요한 경우 List <>는 배열 크기를 선택하는 데 매우 현명하므로 일반적으로 필요하지 않습니다.)
컬렉션 자체의 불변성이 클라이언트 및 공급자 코드 사이의 계약의 일부인 경우 (컬렉션 내의 항목의 불변성이 아닐 수 있음) IEnumerable이 적합하지 않은 경우에는 배열 을 우선적으로 사용해야 합니다.
예를 들어
var str = "This is a string";
var strChars = str.ToCharArray(); // returns array
"strChars"의 수정은 "str"의 기본 유형에 대한 구현 수준의 지식에 관계없이 원래의 "str"객체를 변경하지 않습니다.
하지만
var str = "This is a string";
var strChars = str.ToCharList(); // returns List<char>
strChars.Insert(0, 'X');
이 경우 insert 메소드가 원래 "str"오브젝트를 변경하거나 변경하지 않는 경우 해당 코드 스 니펫만으로는 명확하지 않습니다. 그러한 결정을 내리려면 String에 대한 구현 수준의 지식이 필요하며, 이는 Design by Contract 접근 방식을 위반합니다. String의 경우 큰 문제는 아니지만 거의 모든 경우에 큰 문제가 될 수 있습니다. List를 읽기 전용으로 설정하면 도움이되지만 컴파일 타임이 아닌 런타임 오류가 발생합니다.
To
는 원래 인스턴스를 수정할 수없는 객체를 만드는 strChars as char[]
것이지만, 유효한 경우 원래 객체를 수정할 수 있다고 제안하는 것과는 반대 입니다.
str
내부 배열을 사용하며, ToCharArray
이 배열에 대한 참조를 반환 클라이언트는 변이 수 str
사이즈 남아 고정해도, 해당 배열의 요소를 변화시킴으로써. 그러나 'strChars'를 수정해도 원래의 "str"객체가 변경되지는 않습니다. 내가 여기서 무엇을 놓치고 있습니까? 내가 볼 수 있듯이, 어느 경우이든 클라이언트는 내부 표현에 액세스 할 수 있으며 유형에 관계없이 어떤 종류의 돌연변이를 허용합니다.
대부분의 경우를 사용하면 List
충분합니다. A List
는 내부 배열을 사용하여 데이터를 처리하고 List
현재 용량보다 많은 요소를 추가 할 때 배열의 크기를 자동으로 조정 하므로 용량을 미리 알아야하는 배열보다 사용하기가 더 쉽습니다.
C #의 목록에 대한 자세한 내용 또는 디 컴파일에 대한 자세한 내용은 http://msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx#datastructures20_1_topic5 를 참조 하십시오System.Collections.Generic.List<T>
.
다차원 데이터가 필요한 경우 (예 : 매트릭스 또는 그래픽 프로그래밍) array
대신에 사용할 수 있습니다.
항상 그렇듯이 메모리 나 성능에 문제가 있다면 측정하십시오! 그렇지 않으면 코드에 대해 잘못된 가정을 할 수 있습니다.
배열 대. 목록은 고전적인 유지 관리 성과 성능 문제입니다. 거의 모든 개발자가 따르는 규칙은 둘 다를 쏴야하지만 충돌이 발생할 경우 성능보다 유지 관리 성을 선택해야한다는 것입니다. 이 규칙의 예외는 성능이 이미 문제로 입증 된 경우입니다. 이 원리를 Arrays Vs에 적용하면. 목록을 얻으면 다음과 같이됩니다.
성능 문제가 발생할 때까지 강력한 형식의 목록을 사용하십시오. 성능 문제가 발생하면 어레이로의 드롭 아웃이 유지 관리 측면에서 솔루션에 해를 끼치는 것보다 성능이 뛰어난 솔루션에 도움이 될지 여부를 결정하십시오.
아직 언급되지 않은 또 다른 상황은 많은 수의 항목을 가질 때입니다. 각 항목은 서로 관련되어 있지만 독립적 인 고정 변수 묶음으로 구성됩니다 (예 : 점의 좌표 또는 3D 삼각형의 꼭짓점). 노출 된 필드 구조의 배열은 해당 요소를 다른 위치에서 불가능한 "제자리에서"효율적으로 수정할 수있게합니다. 구조의 배열은 요소를 RAM에 연속적으로 보유하므로 배열 요소에 대한 순차적 액세스는 매우 빠릅니다. 코드가 배열을 통해 많은 순차적 패스를 수행해야하는 상황에서는 구조체의 배열이 배열 또는 클래스 객체 참조의 다른 모음보다 2 : 1만큼 성능이 우수 할 수 있습니다. 더욱이,
배열의 크기를 조정할 수는 없지만 사용중인 요소 수와 함께 배열 참조를 코드에 저장하고 배열을 필요에 따라 더 큰 배열로 바꾸는 것은 어렵지 않습니다. 또는 유사하게 작동 List<T>
하지만 백업 저장소를 노출 한 유형의 코드를 쉽게 작성할 수 있으므로 MyPoints.Add(nextPoint);
또는 중 하나를 말할 수 있습니다 MyPoints.Items[23].X += 5;
. 코드가 목록의 끝을 넘어 액세스하려고 시도하는 경우 후자가 반드시 예외를 throw하지는 않지만 사용법은 개념적으로 매우 유사합니다 List<T>
.
Point[] arr;
, 코드가 예를 들어 말할 수 arr[3].x+=q;
있습니다. 예를 들어 List<Point> list
, 대신 말할 필요가 있습니다 Point temp=list[3]; temp.x+=q; list[3]=temp;
. 경우에 도움이 될 것입니다 List<T>
방법을했다 Update<TP>(int index, ActionByRefRef<T,TP> proc, ref TP params)
. 컴파일러로 전환 할 수 list[3].x+=q;
는 {list.Update(3, (ref int value, ref int param)=>value+=param, ref q);
있지만 그러한 기능은 없습니다.
list[0].X += 3;
목록의 첫 번째 요소의 X 속성에 3을 추가합니다. 그리고 list
A는 List<Point>
및 Point
X와 Y 특성을 가진 클래스
.NET의 목록은 배열의 래퍼이며 내부적으로 배열을 사용합니다. 목록에 대한 작업의 시간 복잡도는 배열에서와 동일하지만 목록의 추가 된 기능 / 사용 편의성 (예 : 자동 크기 조정 및 목록 클래스와 함께 제공되는 메서드)으로 인해 약간의 오버 헤드가 있습니다. 매우 최적화 된 코드를 작성해야하거나 배열 주위에 빌드 된 다른 코드로 작업하는 경우와 같이 강력 하지 않은 이유가 없다면 모든 경우에 목록을 사용하는 것이 좋습니다 .
그것들은 인기가 없지만 게임 프로젝트에서 Arrays의 팬입니다. -반복 속도는 경우에 따라 중요 할 수 있습니다. 각 요소마다 많은 작업을 수행하지 않으면 각 어레이의 오버 헤드가 현저히 줄어 듭니다 .- 도우미 기능으로는 추가 및 제거가 그리 어렵지 않습니다. 그것은 중요하지 않을 수 있습니다-대부분의 경우 여분의 메모리가 낭비됩니다 (구조 배열에서만 중요합니다)-약간 적은 쓰레기와 포인터 및 포인터 추적
즉, 실제로는 Array보다 List를 훨씬 더 자주 사용하지만 각각의 위치가 있습니다.
래퍼 및 열거 오버 헤드를 최적화 할 수 있도록 내장 유형을 나열하면 좋을 것입니다.
배열보다 목록을 채우는 것이 더 쉽습니다. 배열의 경우 정확한 데이터 길이를 알아야하지만 목록의 경우 데이터 크기는 어느 것이나 될 수 있습니다. 또한 목록을 배열로 변환 할 수 있습니다.
List<URLDTO> urls = new List<URLDTO>();
urls.Add(new URLDTO() {
key = "wiki",
url = "https://...",
});
urls.Add(new URLDTO()
{
key = "url",
url = "http://...",
});
urls.Add(new URLDTO()
{
key = "dir",
url = "https://...",
});
// convert a list into an array: URLDTO[]
return urls.ToArray();
아무도 언급하지 않았으므로 C #에서 배열은 목록입니다. MyClass[]
그리고 List<MyClass>
둘 다 구현 IList<MyClass>
합니다. (예 void Foo(IList<int> foo)
처럼 호출 할 수 있습니다 Foo(new[] { 1, 2, 3 })
또는 Foo(new List<int> { 1, 2, 3 })
)
따라서 a List<MyClass>
를 인수로 허용 하지만 기능의 하위 집합 만 사용 하는 메소드를 작성하는 경우 IList<MyClass>
호출자의 편의를 위해 대신 선언 할 수 있습니다 .
세부:
List
만 구현합니다 IList
.
그것은 데이터 구조가 필요한 상황에 전적으로 달려 있습니다. 예를 들어 List를 사용하여 다른 기능이나 서비스에서 사용할 항목을 작성하는 경우이를 수행하는 완벽한 방법입니다.
이제 항목 목록이 있고 표시하려는 경우 웹 페이지 배열에 사용해야 할 컨테이너가 있습니다.
IEnumerable<T>
그러면 버퍼링하는 대신 객체를 스트리밍 할 수 있습니다.
현장에서 캐스팅을 수행하는 능력에 대해 언급 할 가치가 있습니다.
interface IWork { }
class Foo : IWork { }
void Test( )
{
List<Foo> bb = new List<Foo>( );
// Error: CS0029 Cannot implicitly convert type 'System.Collections.Generic.List<Foo>' to 'System.Collections.Generic.List<IWork>'
List<IWork> cc = bb;
Foo[] bbb = new Foo[4];
// Fine
IWork[] ccc = bbb;
}
따라서 Array 는 함수의 반환 유형이나 인수에 사용될 때 약간의 유연성을 제공합니다.
IWork[] GetAllWorks( )
{
List<Foo> fooWorks = new List<Foo>( );
return fooWorks.ToArray( ); // Fine
}
void ExecuteWorks( IWork[] works ) { } // Also accept Foo[]