C #에서 ArrayList와 List <>


412

C # ArrayList과 의 차이점은 무엇입니까 List<>?

그렇지 않은 List<>유형 만 ArrayList있습니까?



5
가까운 질문이지만 정확하게 복제되지는 않는다고 생각합니다. 이것은 List<>일반적으로 물어 보는 반면에, List<object>구체적으로 묻습니다
goodeye

이 매우 유용한 블로그를 찾았다면 도움이 될 것입니다. fintechexplained.blogspot.co.uk/2017/07/…
InfoLearner

답변:


533

그렇습니다. List<T>일반 클래스입니다. 캐스팅하거나 캐스팅하지 않고 특정 유형의 값을 저장할 수 있습니다 object( T이 경우 값 유형 인 경우 boxing / unboxing 오버 헤드가 발생 함 ArrayList). ArrayList단순히 object참조 를 저장 합니다. 일반 컬렉션으로서 List<T>일반 IEnumerable<T>인터페이스를 구현하며 LINQ에서 쉽게 사용할 수 있습니다 ( Cast또는 OfType호출 하지 않아도 됨 ).

ArrayListC #에 제네릭이 없었던 날에 속합니다. 에 찬성하여 더 이상 사용되지 않습니다 List<T>. 당신은 사용하지 말아야 ArrayList새로운 코드에 그 목표 .NET> = 2.0 오래된 API와 인터페이스해야하지 않는 한 그것은 그.


왜 "캐스팅"이 아닌 "권투"를 사용했는지 설명해 주시겠습니까? 여기서 무슨 권투가 발생합니까? 객체가 할당 / 할당되지 않습니까?
Benjamin Gruenbaum

2
@BenjaminGruenbaum 캐스팅이 더 일반적 일 것입니다. 즉, 런타임에서 실제 차이점은 값 유형을 처리 할 때입니다 ( "boxing"을 작성할 때 가정 한 것임). 참조 유형의 경우 동작은 ArrayList런타임 과 사실상 동일 합니다. 그러나 정적으로는로 캐스팅해야합니다 ArrayList.
Mehrdad Afshari

ArrayList가 암시 적으로 허용하기 때문에 프레임 워크가 T를 "객체"유형으로 제한 해야하는지 궁금합니다.
rajibdotnet

형식화되지 않은 컬렉션의 폐기에 대해서는 유해한 것으로 간주되는 제네릭
Ant_222

@ Ant_222, 그 블로그는 거의 15 년 전에 작성되었습니다. 지난 10 년 동안의 증거는 제네릭이 해롭지 않다는 것을 보여주었습니다. :)
Scott Adams

101

사용 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에서 가져올 때 유형을 확인할 수 있습니다. 요즘 사람들은 객체를 사용하므로 ArrayList가 더 이상 필요하지 않습니다.
전환

1
나는 정당화에 +1하지만 오류를 피하기 위해 배열 목록에 if (num is int) {} 할 수있다
Mina Gabriel

캐스팅 오류 및 권투 오버 헤드를 방지하십시오. 제네릭의 일반적인 이유는 거의 같습니다.
marsze

26

위의 포인트에 추가합니다. 사용하여 ArrayList64 비트 운영 시스템은 32 비트 운영체제에서 사용하는 것보다 2 배의 메모리 걸린다. 한편, 일반 목록 List<T>은보다 적은 메모리를 사용합니다 ArrayList.

예를 들어 ArrayList32 비트에서 19MB를 사용하는 경우 64 비트에서 39MB가 필요합니다. 그러나 List<int>32 비트 의 일반 8MB 목록이있는 경우 64 비트의 경우 8.1MB 만 사용되므로 ArrayList와 비교할 때 481 %의 차이가 있습니다.

출처 : 기본 유형 및 64 비트에 대한 ArrayList와 일반 목록


5
이는 참조 유형이 아닌 값 유형을 저장하는 경우에만 해당됩니다. 차이점은 arraylist는 포인터 만 포함 할 수 있고 데이터 자체는 다른 곳에 저장해야하기 때문입니다. 반면에 값 유형은 목록에 직접 저장할 수 있습니다.
라스무스 담 가드 닐슨

19

추가해야 할 또 다른 차이점은 스레드 동기화와 관련이 있습니다.

ArrayList컬렉션 주위의 스레드 안전 래퍼를 반환하는 Synchronized 속성을 통해 스레드 안전을 제공합니다. 랩퍼는 모든 추가 또는 제거 조작에서 전체 콜렉션을 잠그면 작동합니다. 따라서 컬렉션에 액세스하려는 각 스레드는 해당 차례가 하나의 잠금을 수행 할 때까지 기다려야합니다. 이는 확장 할 수 없으며 대규모 컬렉션의 경우 성능이 크게 저하 될 수 있습니다.

List<T>스레드 동기화를 제공하지 않습니다. 사용자 코드는 여러 스레드에서 동시에 항목을 추가하거나 제거 할 때 모든 동기화를 제공해야합니다.

자세한 내용 은 .Net Framework의 스레드 동기화


ArrayList피할 수 있다면 사용해야한다고 말하는 것은 아니지만 이것이 어리석은 이유입니다. 래퍼는 전적으로 선택 사항입니다. 잠금이 필요하지 않거나 더 세밀한 제어가 필요한 경우 래퍼를 사용하지 마십시오.
Thorarin

1
스레드 안전성을 원한다면 ArrayList를 고려하기 전에 System.Collections.Concurrent 네임 스페이스를 살펴 보는 것이 좋습니다.
Ykok

15

간단한 대답은

ArrayList는 제네릭이 아닙니다

  • 객체 유형이므로 모든 데이터 유형을 저장할 수 있습니다.
  • String, int, employee 및 object와 같은 값 (값 유형 또는 참조 유형)을 ArrayList에 저장할 수 있습니다. (참고 및)
  • 권투와 Unboxing이 일어날 것입니다.
  • 안전하지 않습니다.
  • 오래되었습니다.

일반 목록

  • 유형 유형이므로 런타임시 T를 지정할 수 있습니다.
  • 선언에 따라 유형 T (문자열 또는 정수 또는 직원 또는 객체)의 유일한 값을 저장할 수 있습니다. (참고 또는)
  • 권투와 Unboxing이 발생하지 않습니다.
  • 안전한 타입.
  • 최신입니다.

예:

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/


4

ArrayList서로 다른 유형의 데이터를 List<>수집 하는 반면 유사한 유형의 자체 depedencties를 수집합니다.


3

ArrayList형식이 안전하지만 형식이 안전하지 않습니다 List<T>. 단순 :).


2

성능은 이미 몇 가지 답변에서 차별화 요소로 언급되었지만“ 어느 정도 느린 ArrayList가요? ”및“ 왜 전체적으로 느려 집니까? ”, 아래를보세요.

값 유형이 요소로 사용될 때마다 성능이 크게 저하됩니다 ArrayList. 단순히 요소를 추가하는 경우를 고려하십시오. 권투가 계속 진행됨에 따라 ArrayListAdd는 object매개 변수 만 사용 하므로 가비지 수집기는보다 많은 작업을 수행하도록 트리거됩니다 List<T>.

시차는 얼마입니까? 보다 몇 배 이상 느립니다 List<T>. 10mil int 값을 ArrayListvs에 추가하는 코드에서 발생하는 일을 살펴보십시오 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 개의 가비지 콜렉션이 필요했습니다.


1

나는 사이의 차이를 생각 ArrayList하고 List<T>있습니다 :

  1. List<T>여기서 T는 value-type보다 빠릅니다 ArrayList. 이것은 List<T>boxing / unboxing을 피하기 때문입니다 (여기서 T는 value-type입니다).
  2. 많은 출처에 따르면 일반적으로 ArrayList이전 버전과의 호환성을 위해서만 사용됩니다. (실제 차이는 없지만 중요한 메모라고 생각합니다).
  3. 비 제네릭 ArrayList을 사용 하면 반사가 더 쉽습니다.List<T>
  4. ArrayListIsSynchronized속성 이 있습니다. 따라서 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
  5. ArrayList보유 ArrayList.SyncRootsyncronisation (사용할 수있는 속성 은 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)
        {
            // ...
        }
    }

0

.NET Framework 설명서 에서 언급 한 바와 같이

ArrayList새로운 개발에 클래스를 사용하지 않는 것이 좋습니다 . 대신 일반 List<T> 클래스 를 사용하는 것이 좋습니다 . 이 ArrayList클래스는 이기종 객체 컬렉션을 보유하도록 설계되었습니다. 그러나 항상 최상의 성능을 제공하는 것은 아닙니다. 대신 다음을 권장합니다.

  • 이기종 개체 컬렉션의 경우 List<Object>(C #) 또는 List(Of Object)(Visual Basic) 형식을 사용하십시오.
  • 동종의 객체 컬렉션을 위해서는 List<T>클래스를 사용하십시오 .

참조 비 제네릭 컬렉션을 사용할 수 없습니다

표는 제네릭이 아닌 컬렉션 유형을 일반 형식으로 바꾸는 방법을 보여줍니다.


-2

"목록"을 사용하면 전송 오류를 방지 할 수 있습니다. 런타임 캐스팅 오류를 피하는 것이 매우 유용합니다.

예:

여기서 (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.
        }
    }

이것은 3 년 전에 주어진 해답 용어 외에 무엇을 추가합니까? 소스에 연결하지 않고 서식을 올바르게 지정하지 않고 거의 동일한 텍스트를 그대로 사용합니다.
Douglas Zare

-3

귀하의 데이터를 아는 것에 대한 모든 것. 효율성을 기준으로 코드를 계속 확장하려면 유형, 특히 '사용자 정의 유형'에 대해 항상 궁금해하는 불필요한 단계없이 데이터를 해독하는 방법으로 목록 옵션을 선택해야합니다. 기계가 그 차이를 이해하고 실제로 처리하고있는 데이터 유형이 무엇인지 판단 할 수 있다면 왜 'IF THEN ELSE'결정의 진행을 통해 방해가됩니까? 저의 철학은 기계 작업을하는 대신 기계를 작동시키는 것입니까? 다른 객체 코드 명령의 고유 한 차이점을 아는 것은 코드를 효율적으로 만드는 데 큰 도움이됩니다.

톰 존슨 (하나의 입구 ... 하나의 출구)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.