code

C # 컬렉션 이니셜 라이저가 이런 방식으로 작동하는 이유는 무엇입니까?

codestyles 2020. 12. 24. 23:44
반응형

C # 컬렉션 이니셜 라이저가 이런 방식으로 작동하는 이유는 무엇입니까?


나는 C # 컬렉션 이니셜 라이저를보고 있었고 구현이 매우 실용적이지만 C #의 다른 것과는 매우 다르다는 것을 알았습니다.

다음과 같은 코드를 만들 수 있습니다.

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        Test test = new Test { 1, 2, 3 };
    }
}

class Test : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        throw new NotImplementedException();
    }

    public void Add(int i) { }
}

컴파일러 (구현 IEnumerable및 a public void Add)에 대한 최소 요구 사항을 충족했기 때문에 이것은 작동하지만 분명히 가치가 없습니다.

C # 팀이 더 엄격한 요구 사항 집합을 만들지 못하게하는 이유가 무엇입니까? 즉,이 구문을 컴파일하기 위해 컴파일러에서 유형이 ICollection?를 구현하도록 요구하지 않는 이유는 무엇입니까? 그것은 다른 C # 기능의 정신에서 더 많이 보입니다.


귀하의 관찰은 사실입니다. 사실, Microsoft C # 언어 PM 인 Mads Torgersen이 만든 것과 동일합니다.

Mads는 2006 년 10 월이 주제에 대해 What Is a Collection? 이라는 제목의 게시물을 올렸습니다 . 그가 쓴 글 :

인정, 우리는 쓸모없는 옆에있는 System.Collections.ICollection을 사용하여 프레임 워크의 첫 번째 버전에서 그것을 날려 버렸습니다. 그러나 우리는 제네릭이 .NET 프레임 워크 2.0에 등장했을 때 꽤 잘 해결했습니다. System.Collections.Generic.ICollection <T>를 사용하면 요소를 추가 및 제거하고, 열거하고, 계수하고, 멤버 자격을 확인할 수 있습니다.

분명히 그때부터는 누구나 컬렉션을 만들 때마다 ICollection <T>를 구현할 것입니다. 별로. 다음은 LINQ를 사용하여 실제로 컬렉션이 무엇인지 알아보고 C # 3.0에서 언어 디자인을 변경 한 방법입니다.

ICollection<T>프레임 워크에는 14 개의 구현 만 있지만 IEnumerable공용 Add()메소드 를 구현 하고 갖는 189 개의 클래스가 있습니다.

이 접근 방식에는 숨겨진 이점이 있습니다. ICollection<T>인터페이스를 기반으로했다면 정확히 하나의 지원되는 Add()방법 이 있었을 것 입니다.

대조적으로, 그들이 취한 접근 방식은 컬렉션의 이니셜 라이저가 Add()메서드에 대한 인수 집합을 형성한다는 것을 의미합니다 .

설명을 위해 코드를 약간 확장 해 보겠습니다.

class Test : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        throw new NotImplementedException();
    }

    public void Add(int i) { }

    public void Add(int i, string s) { }
}

이제 다음과 같이 작성할 수 있습니다.

class Program
{
    static void Main()
    {
        Test test 
            = new Test 
            {
                1, 
                { 2, "two" },
                3 
            };
    }
}

I thought about this too, and the answer which satisfies me the most is that ICollection has many methods other than Add, such as: Clear, Contains, CopyTo, and Remove. Removing elements or clearing has nothing to do with being able to support the object initializer syntax, all you need is an Add().

If the framework was designed granularly enough, and there was an ICollectionAdd interface, then it would've had a "perfect" design. But I honestly don't think that would have added much value, having one method per interface. IEnumerable + Add seems like a hackish approach, but when you think about it, it's a better alternative.

EDIT: This is not the only time C# has approached a problem with this type of solution. Since .NET 1.1, foreach uses duck typing to enumerate a collection, all your class needs to implement is GetEnumerator, MoveNext and Current. Kirill Osenkov has a post which asks your question as well.


(I know I am 3 years late on this, but I was not satisfied with the existing answers.)

why, in order for this syntax to compile, does the compiler not require that the type implement ICollection?

I'll reverse your question: What use would it be if the compiler had requirements that are not really needed?

Non-ICollection classes too can benefit from the collection initializer syntax. Consider classes that allow adding data into them, without allowing access to previously added data.

Personally, I like to use the new Data { { ..., ... }, ... } syntax to add a light, DSL-like look to the code of my unit tests.

Actually, I'd rather weaken the requirement, so that I can use the nice-looking syntax without even having to bother implementing IEnumerable. Collection initializers are pure syntactic sugar to Add(), they shouldn't require anything else.

ReferenceURL : https://stackoverflow.com/questions/459652/why-do-c-sharp-collection-initializers-work-this-way

반응형