ProgramingTip

C #의 공변 및 반 변성 인터페이스 이해

bestdevel 2020. 10. 5. 08:10
반응형

C #의 공변 및 반 변성 인터페이스 이해


C #에서 읽고있는 교과서에서 많은 문제를 발견하고 부족으로 인해 이해하는 어려움이 있습니다.

그들이 무엇인지 그리고 그들이 거기에서 사용하는 것에 대한 간결한 설명이 있습니까?

도구하기 위해 편집 :

공변 인터페이스 :

interface IBibble<out T>
.
.

반 변성 인터페이스 :

interface IBibble<in T>
.
.

를 사용 <out T>하면 인터페이스 참조를 계층 구조에서 상위 항목으로 처리 할 수 ​​있습니다.

를 사용 <in T>하면 인터페이스 참조를 계층 구조에서 낮게 처리 할 수 ​​있습니다.

좀 더 영어로 설명해 보겠습니다.

동물원에서 동물 목록을 검색하고 처리하려고 가정 해 보겠습니다. 동물원에있는 모든 동물에는 이름과 고유 ID가 있습니다. 어떤 동물은 포유류이고, 어떤 것은 파충류이고, 어떤 것은 양서류이고, 어떤 것은 물고기입니다. 그러나 모두 그들은 동물입니다.

따라서 동물 목록 (유형의 동물 포함)을 사용하면 모든 동물에 이름이 사용하면 모든 동물의 이름이 사용할 수 있습니다.

그러나 물고기 목록 만 있으면 동물처럼 취급 해야하는 경우에는 어떻게 보험이 있습니까? 기능으로 작동하지만 C # 3.0 이전에서는 코드 조각이되지 않습니다.

IEnumerable<Animal> animals = GetFishes(); // returns IEnumerable<Fish>

그 이유는 컴파일러가 동물 컬렉션을 검색 한 후 의도 한 바를 "알지"못하거나 할 수 있기 때문입니다. 아는 한, IEnumerable<T>개체를 목록에 다시 넣는 방법이있을 수 있으며, 딱딱한 물고기가 아닌 동물을 물고기 만 포함해야하는 컬렉션에 넣을 수 있습니다.

즉, 컴파일러는 허용되지 않는다.

animals.Add(new Mammal("Zebra"));

따라서 컴파일러는 코드를 완전히 제거합니다. 이것은 공분산입니다.

반공 변성을 생생하게 보겠습니다.

우리 동물원은 모든 동물을 다룰 수 있기 때문에 확실히 물고기를 다룰 수 있으므로 동물원에 물고기를 조금 추가해 보겠습니다.

C # 3.0 이하에서는 설명하지 않습니다.

List<Fish> fishes = GetAccessToFishes(); // for some reason, returns List<Animal>
fishes.Add(new Fish("Guppy"));

여기에서 컴파일러 List<Animal>물고기가 동물 모든이기 때문에 메서드가 단순히 반환 하더라도이 코드 조각을 허용 있으므로 유형을 다음과 같이 변경하면됩니다.

List<Animal> fishes = GetAccessToFishes();
fishes.Add(new Fish("Guppy"));

작동 작동하지만 컴파일러는이 작업을 수행하지 않는지 확인할 수 없습니다.

List<Fish> fishes = GetAccessToFishes(); // for some reason, returns List<Animal>
Fish firstFist = fishes[0];

목록은 실제로 동물 목록에서 허용되지 않습니다.

따라서 반대 및 공분산은 참조를 처리하는 방법과이를 사용하여 수행 할 수있는 작업입니다.

C # 4.0 inout키워드는 특히 인터페이스를 둘 중 하나로 표시합니다. 를 사용 in하면 제네릭 유형 (일반적으로 T)을 입력 위치에 배치 할 수 있습니다. 이는 메서드 인수와 쓰기 전용 속성을 의미합니다.

를 사용하면 출력 위치에 out제네릭 유형을 배치 할 수 있습니다. 이는 메소드 반환 값, 읽기 전용 속성 및 out 메소드 변수입니다.

이렇게하면 코드로 의도 한 작업을 수행 할 수 있습니다.

IEnumerable<Animal> animals = GetFishes(); // returns IEnumerable<Fish>
// since we can only get animals *out* of the collection, every fish is an animal
// so this is safe

List<T> T에 내부 내부 방향이 모두 있으므로 공변도 반 변이도 있고 다음과 같이 할 수있는 인터페이스입니다.

interface IWriteOnlyList<in T>
{
    void Add(T value);
}

다음과 같이 할 수 있습니다.

IWriteOnlyList<Fish> fishes = GetWriteAccessToAnimals(); // still returns
                                                            IWriteOnlyList<Animal>
fishes.Add(new Fish("Guppy")); <-- this is now safe

다음은 개념을 몇 가지 동영상입니다.

예를 들면 다음과 같습니다.

namespace SO2719954
{
    class Base { }
    class Descendant : Base { }

    interface IBibbleOut<out T> { }
    interface IBibbleIn<in T> { }

    class Program
    {
        static void Main(string[] args)
        {
            // We can do this since every Descendant is also a Base
            // and there is no chance we can put Base objects into
            // the returned object, since T is "out"
            // We can not, however, put Base objects into b, since all
            // Base objects might not be Descendant.
            IBibbleOut<Base> b = GetOutDescendant();

            // We can do this since every Descendant is also a Base
            // and we can now put Descendant objects into Base
            // We can not, however, retrieve Descendant objects out
            // of d, since all Base objects might not be Descendant
            IBibbleIn<Descendant> d = GetInBase();
        }

        static IBibbleOut<Descendant> GetOutDescendant()
        {
            return null;
        }

        static IBibbleIn<Base> GetInBase()
        {
            return null;
        }
    }
}

다음이 될 수 있습니다.

public List<Descendant> GetDescendants() ...
List<Base> bases = GetDescendants();
bases.Add(new Base()); <-- uh-oh, we try to add a Base to a Descendant

아니면 이거 :

public List<Base> GetBases() ...
List<Descendant> descendants = GetBases(); <-- uh-oh, we try to treat all Bases
                                               as Descendants

이 게시물 은 내가 주제에 대해 읽은 것 중 최고입니다.

간단히 말해서, 공분산 / 반 변성 / 불변은 자동 유형 캐스팅 (기본에서 파생으로 또는 그 반대)을 다룹니다. 이러한 유형 캐스트는 캐스트 된 객체에 대해 수행되는 읽기 / 쓰기 작업과 관련하여 일부 보장이 적용되는 경우에만 가능합니다. 자세한 내용은 게시물을 읽어보십시오.

참고 URL : https://stackoverflow.com/questions/2719954/understanding-covariant-and-contravariant-interfaces-in-c-sharp

반응형