C # ArrayList
과 의 차이점은 무엇입니까 List<>
?
그렇지 않은 List<>
유형 만 ArrayList
있습니까?
List<>
일반적으로 물어 보는 반면에, List<object>
구체적으로 묻습니다
C # ArrayList
과 의 차이점은 무엇입니까 List<>
?
그렇지 않은 List<>
유형 만 ArrayList
있습니까?
List<>
일반적으로 물어 보는 반면에, List<object>
구체적으로 묻습니다
답변:
그렇습니다. List<T>
일반 클래스입니다. 캐스팅하거나 캐스팅하지 않고 특정 유형의 값을 저장할 수 있습니다 object
( T
이 경우 값 유형 인 경우 boxing / unboxing 오버 헤드가 발생 함 ArrayList
). ArrayList
단순히 object
참조 를 저장 합니다. 일반 컬렉션으로서 List<T>
일반 IEnumerable<T>
인터페이스를 구현하며 LINQ에서 쉽게 사용할 수 있습니다 ( Cast
또는 OfType
호출 하지 않아도 됨 ).
ArrayList
C #에 제네릭이 없었던 날에 속합니다. 에 찬성하여 더 이상 사용되지 않습니다 List<T>
. 당신은 사용하지 말아야 ArrayList
새로운 코드에 그 목표 .NET> = 2.0 오래된 API와 인터페이스해야하지 않는 한 그것은 그.
ArrayList
런타임 과 사실상 동일 합니다. 그러나 정적으로는로 캐스팅해야합니다 ArrayList
.
사용 List<T>
당신은 오류를 캐스팅 방지 할 수 있습니다. 런타임 캐스팅 오류 를 피하는 것이 매우 유용합니다 .
예:
여기서 (를 사용하여 ArrayList
)이 코드를 컴파일 할 수 있지만 나중에 실행 오류가 표시됩니다.
ArrayList array1 = new ArrayList();
array1.Add(1);
array1.Add("Pony"); //No error at compile process
int total = 0;
foreach (int num in array1)
{
total += num; //-->Runtime Error
}
를 사용 List
하면 다음 오류를 피할 수 있습니다.
List<int> list1 = new List<int>();
list1.Add(1);
//list1.Add("Pony"); //<-- Error at compile process
int total = 0;
foreach (int num in list1 )
{
total += num;
}
참조 : MSDN
위의 포인트에 추가합니다. 사용하여 ArrayList
64 비트 운영 시스템은 32 비트 운영체제에서 사용하는 것보다 2 배의 메모리 걸린다. 한편, 일반 목록 List<T>
은보다 적은 메모리를 사용합니다 ArrayList
.
예를 들어 ArrayList
32 비트에서 19MB를 사용하는 경우 64 비트에서 39MB가 필요합니다. 그러나 List<int>
32 비트 의 일반 8MB 목록이있는 경우 64 비트의 경우 8.1MB 만 사용되므로 ArrayList와 비교할 때 481 %의 차이가 있습니다.
추가해야 할 또 다른 차이점은 스레드 동기화와 관련이 있습니다.
ArrayList
컬렉션 주위의 스레드 안전 래퍼를 반환하는 Synchronized 속성을 통해 스레드 안전을 제공합니다. 랩퍼는 모든 추가 또는 제거 조작에서 전체 콜렉션을 잠그면 작동합니다. 따라서 컬렉션에 액세스하려는 각 스레드는 해당 차례가 하나의 잠금을 수행 할 때까지 기다려야합니다. 이는 확장 할 수 없으며 대규모 컬렉션의 경우 성능이 크게 저하 될 수 있습니다.
List<T>
스레드 동기화를 제공하지 않습니다. 사용자 코드는 여러 스레드에서 동시에 항목을 추가하거나 제거 할 때 모든 동기화를 제공해야합니다.
자세한 내용 은 .Net Framework의 스레드 동기화
ArrayList
피할 수 있다면 사용해야한다고 말하는 것은 아니지만 이것이 어리석은 이유입니다. 래퍼는 전적으로 선택 사항입니다. 잠금이 필요하지 않거나 더 세밀한 제어가 필요한 경우 래퍼를 사용하지 마십시오.
간단한 대답은
ArrayList arrayList = new ArrayList();
List<int> list = new List<int>();
arrayList.Add(1);
arrayList.Add("String");
arrayList.Add(new object());
list.Add(1);
list.Add("String"); // Compile-time Error
list.Add(new object()); // Compile-time Error
Microsoft 공식 문서를 읽으십시오 : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/
참고 : 차이점을 이해하기 전에 Generics를 알아야합니다. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
ArrayList
서로 다른 유형의 데이터를 List<>
수집 하는 반면 유사한 유형의 자체 depedencties를 수집합니다.
성능은 이미 몇 가지 답변에서 차별화 요소로 언급되었지만“ 어느 정도 느린 ArrayList
가요? ”및“ 왜 전체적으로 느려 집니까? ”, 아래를보세요.
값 유형이 요소로 사용될 때마다 성능이 크게 저하됩니다 ArrayList
. 단순히 요소를 추가하는 경우를 고려하십시오. 권투가 계속 진행됨에 따라 ArrayList
Add는 object
매개 변수 만 사용 하므로 가비지 수집기는보다 많은 작업을 수행하도록 트리거됩니다 List<T>
.
시차는 얼마입니까? 보다 몇 배 이상 느립니다 List<T>
. 10mil int 값을 ArrayList
vs에 추가하는 코드에서 발생하는 일을 살펴보십시오 List<T>
.
'Mean'열에서 노란색으로 강조 표시된 런타임 차이는 5 배 입니다. 또한 각각에 대해 수행 된 가비지 콜렉션 수의 차이가 빨간색으로 강조 표시됩니다 (GC / 1000 실행 없음).
프로파일 러를 사용하여 진행 상황을 신속하게 확인 하면 실제로 요소를 추가하는 대신 대부분의 시간이 GC를 수행하는 데 소요 됩니다. 아래의 갈색 막대는 가비지 콜렉터 활동 차단을 나타냅니다.
위의 ArrayList
시나리오에서 진행되는 작업에 대한 자세한 분석은 https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/에서 작성했습니다 .
Jeffrey Richter의“CLR via C #”에서도 비슷한 결과가 나옵니다. 12 장 (일반) :
[…] 컴퓨터에서이 프로그램의 릴리스 빌드 (최적화가 설정된 상태)를 컴파일하고 실행할 때 다음과 같은 결과가 나타납니다.
00 : 00 : 01.6246959 (GCs = 6) List <Int32>
00 : 00 : 10.8555008 (GCs = 390) Int32의
배열 목록 00 : 00 : 02.5427847 (GCs = 4) List <String>
00 : 00 : 02.7944831 (GCs = 7 ) 문자열의 ArrayList여기서 출력은 Int32 유형으로 일반 목록 알고리즘을 사용하는 것이 Int32와 함께 제네릭이 아닌 ArrayList 알고리즘을 사용하는 것보다 훨씬 빠르다는 것을 보여줍니다. 실제로, 그 차이는 놀랍습니다 : 1.6 초 대 거의 11 초. ~ 7 배 빠릅니다 ! 또한 ArrayList에 값 유형 (Int32)을 사용하면 많은 복싱 작업이 발생하여 390 개의 가비지 수집이 발생합니다. 한편, List 알고리즘에는 6 개의 가비지 콜렉션이 필요했습니다.
나는 사이의 차이를 생각 ArrayList
하고 List<T>
있습니다 :
List<T>
여기서 T는 value-type보다 빠릅니다 ArrayList
. 이것은 List<T>
boxing / unboxing을 피하기 때문입니다 (여기서 T는 value-type입니다).ArrayList
이전 버전과의 호환성을 위해서만 사용됩니다. (실제 차이는 없지만 중요한 메모라고 생각합니다).ArrayList
을 사용 하면 반사가 더 쉽습니다.List<T>
ArrayList
IsSynchronized
속성 이 있습니다. 따라서 syncronised를 쉽게 만들고 사용할 수 있습니다 ArrayList
. 에 IsSynchronized
대한 속성을 찾지 못했습니다 List<T>
. 또한 이러한 유형의 동기화는 상대적으로 비효율적입니다 ( msdn ).
var arraylist = new ArrayList();
var arrayListSyncronized = ArrayList.Synchronized(arraylist
Console.WriteLine($"syncronized {arraylist.IsSynchronized}");
Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");
var list = new List<object>();
var listSyncronized = ArrayList.Synchronized(list);
Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
ArrayList
보유 ArrayList.SyncRoot
syncronisation (사용할 수있는 속성 은 MSDN ). 속성 List<T>
이 없으므로 SyncRoot
다음 구성에서는 사용하는 경우 일부 객체를 사용해야합니다 List<T>
.
ArrayList myCollection = new ArrayList();
lock(myCollection.SyncRoot) // ofcourse you can use another object for this goal
{
foreach (object item in myCollection)
{
// ...
}
}
.NET Framework 설명서 에서 언급 한 바와 같이
ArrayList
새로운 개발에 클래스를 사용하지 않는 것이 좋습니다 . 대신 일반List<T>
클래스 를 사용하는 것이 좋습니다 . 이ArrayList
클래스는 이기종 객체 컬렉션을 보유하도록 설계되었습니다. 그러나 항상 최상의 성능을 제공하는 것은 아닙니다. 대신 다음을 권장합니다.
- 이기종 개체 컬렉션의 경우
List<Object>
(C #) 또는List(Of Object)
(Visual Basic) 형식을 사용하십시오.- 동종의 객체 컬렉션을 위해서는
List<T>
클래스를 사용하십시오 .
"목록"을 사용하면 전송 오류를 방지 할 수 있습니다. 런타임 캐스팅 오류를 피하는 것이 매우 유용합니다.
예:
여기서 (ArrayList를 사용하여)이 코드를 컴파일 할 수 있지만 나중에 실행 오류가 표시됩니다.
// Create a new ArrayList
System.Collections.ArrayList mixedList = new System.Collections.ArrayList();
// Add some numbers to the list
mixedList.Add(7);
mixedList.Add(21);
// Add some strings to the list
mixedList.Add("Hello");
mixedList.Add("This is going to be a problem");
System.Collections.ArrayList intList = new System.Collections.ArrayList();
System.Collections.ArrayList strList = new System.Collections.ArrayList();
foreach (object obj in mixedList)
{
if (obj.GetType().Equals(typeof(int)))
{
intList.Add(obj);
}
else if (obj.GetType().Equals(typeof(string)))
{
strList.Add(obj);
}
else
{
// error.
}
}
귀하의 데이터를 아는 것에 대한 모든 것. 효율성을 기준으로 코드를 계속 확장하려면 유형, 특히 '사용자 정의 유형'에 대해 항상 궁금해하는 불필요한 단계없이 데이터를 해독하는 방법으로 목록 옵션을 선택해야합니다. 기계가 그 차이를 이해하고 실제로 처리하고있는 데이터 유형이 무엇인지 판단 할 수 있다면 왜 'IF THEN ELSE'결정의 진행을 통해 방해가됩니까? 저의 철학은 기계 작업을하는 대신 기계를 작동시키는 것입니까? 다른 객체 코드 명령의 고유 한 차이점을 아는 것은 코드를 효율적으로 만드는 데 큰 도움이됩니다.
톰 존슨 (하나의 입구 ... 하나의 출구)