source

C#의 배열과 같은 목록을 초기화할 수 있는 이유는 무엇입니까?

itover 2023. 4. 27. 22:12
반응형

C#의 배열과 같은 목록을 초기화할 수 있는 이유는 무엇입니까?

오늘 저는 C#에서 다음과 같은 일을 할 수 있다는 것을 알고 놀랐습니다.

List<int> a = new List<int> { 1, 2, 3 };

내가 왜 이걸 할 수 있을까요?어떤 생성자라고 합니까?어떻게 제 수업으로 이것을 할 수 있을까요?이것이 배열을 초기화하는 방법이라는 것을 알고 있지만 배열은 언어 항목이고 목록은 단순 개체입니다...

이는 의 컬렉션 이니셜라이저 구문의 일부입니다.NET. 다음과 같은 경우에는 모든 컬렉션에서 이 구문을 사용할 수 있습니다.

  • 구현합니다.IEnumerable(바람직하게는IEnumerable<T>)

  • 다음과 같은 이름의 메서드가 있습니다.Add(...)

기본 생성자가 호출된 다음Add(...)이니셜라이저의 각 멤버에 대해 호출됩니다.

따라서 다음 두 블록은 거의 동일합니다.

List<int> a = new List<int> { 1, 2, 3 };

그리고.

List<int> temp = new List<int>();
temp.Add(1);
temp.Add(2);
temp.Add(3);
List<int> a = temp;

원하는 경우 대체 생성자를 호출할 수 있습니다. 예를 들어 과도한 크기 조정을 방지하기 위해List<T>성장 중 등:

// Notice, calls the List constructor that takes an int arg
// for initial capacity, then Add()'s three items.
List<int> a = new List<int>(3) { 1, 2, 3, }

참고:Add()메소드는 단일 항목을 취할 필요가 없습니다. 예를 들어,Add()을 위한 방법.Dictionary<TKey, TValue>두 가지 항목을 사용합니다.

var grades = new Dictionary<string, int>
    {
        { "Suzy", 100 },
        { "David", 98 },
        { "Karen", 73 }
    };

대략 다음과 같습니다.

var temp = new Dictionary<string, int>();
temp.Add("Suzy", 100);
temp.Add("David", 98);
temp.Add("Karen", 73);
var grades = temp;

따라서 이를 자신의 클래스에 추가하려면 앞서 언급한 바와 같이 구현하기만 하면 됩니다.IEnumerable(다시 말하지만, 가급적이면.IEnumerable<T>) 및 하나 이상 생성Add()메서드:

public class SomeCollection<T> : IEnumerable<T>
{
    // implement Add() methods appropriate for your collection
    public void Add(T item)
    {
        // your add logic    
    }

    // implement your enumerators for IEnumerable<T> (and IEnumerable)
    public IEnumerator<T> GetEnumerator()
    {
        // your implementation
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

그런 다음 BCL 컬렉션과 마찬가지로 사용할 수 있습니다.

public class MyProgram
{
    private SomeCollection<int> _myCollection = new SomeCollection<int> { 13, 5, 7 };    

    // ...
}

(자세한 내용은 MSDN 참조)

이것은 통사 설탕이라고 불립니다.

List<T>컴파일러는 "compiler" 클래스이지만, 당신의 삶을 더 쉽게 만들기 위해 그것에 특별한 대우를 해줍니다.

이것을 수집 이니셜라이저라고 합니다.구현해야 합니다.IEnumerable<T>그리고.Add방법.

C# Version 3.0 사양에 따라 "Collection Initializer가 적용되는 Collection 객체는 System을 구현하는 유형이어야 합니다.컬렉션.포괄적인.저는 정확히 한 개의 T를 수집합니다."

그러나 이 정보는 이 글에서 부정확한 것으로 보입니다. 아래 의견에서 Eric Lippert의 설명을 참조하십시오.

기본적으로 Add 메서드를 구현하기 위해 컬렉션을 필요로 하는 컬렉션 이니셜라이저 덕분에 작동합니다.

수집 이니셜라이저의 또 다른 멋진 점은 여러 개의 오버로드가 발생할 수 있다는 것입니다.Add메소드를 사용하면 동일한 이니셜라이저로 모두 호출할 수 있습니다!예를 들어 다음과 같이 작동합니다.

public class MyCollection<T> : IEnumerable<T>
{
    public void Add(T item, int number)
    {

    }
    public void Add(T item, string text) 
    {

    }
    public bool Add(T item) //return type could be anything
    {

    }
}

var myCollection = new MyCollection<bool> 
{
    true,
    { false, 0 },
    { true, "" },
    false
};

올바른 과부하를 호출합니다.또한 이름을 가진 메소드만 찾습니다.Add반환 유형은 아무 것이나 될 수 있습니다.

구문과 같은 배열이 일련의 방식으로 전환되고 있습니다.Add()전화가 걸려오는 전화.

이것을 훨씬 더 흥미로운 예로 보려면 C#에서 처음에 불법으로 들리는 두 가지 흥미로운 작업을 수행하는 다음 코드를 생각해 보십시오. 1) 읽기 전용 속성 설정, 2) 이니셜라이저와 같은 배열로 목록 설정.

public class MyClass
{   
    public MyClass()
    {   
        _list = new List<string>();
    }
    private IList<string> _list;
    public IList<string> MyList 
    { 
        get
        { 
            return _list;
        }
    }
}
//In some other method
var sample = new MyClass
{
    MyList = {"a", "b"}
};

1) MyList는 읽기 전용이고 2) Array Initializer로 목록을 설정했지만 이 코드는 완벽하게 작동합니다.

이것이 작동하는 이유는, 객체 초기화기의 일부인 코드에서 컴파일러는 항상 다음과 같이 회전하기 때문입니다.{}Add()읽기 전용 필드에서도 완벽하게 합법적인 통화

언급URL : https://stackoverflow.com/questions/8853937/why-can-i-initialize-a-list-like-an-array-in-c

반응형