C#: 공동 및 역변
, , , 。
할당 호환성
그 전에'부치 호환성'을 알아보면 파생류 대상이'기류 대상'에게 부치할 수 있고 그렇지 않으면 안 된다.이 개념을 이해하면 나중에 시간이 지나면 헷갈릴 수 있지만 사실 방문의 안전성으로만 이해하면 쉽게 잊혀지지 않는다.파생류는 기류에서 물려받은 것이고 자신의 개인적인 것도 있다.
그래서 안전성에서 볼 때 개다리가 토끼다리가 되지 않도록 토끼집(메모리)의 안전을 지키기 위해 기류는 파생류에 값을 부여할 수 없다.
협동하여 변화시키다
먼저 이전 코드의 일치된 부분을 보십시오:
class Animal {
public int Legs = 4;}
class Dog : Animal {
}
delegate T Factory<out T>( );
class Program
{
static Dog MakeDog()
{
return new Dog();
}
static void main()
{
Factory<Dog> dogMaker = MakeDog;
Factory<Animal> animalMaker = dogMaker;
Console.WriteLine(animalMaker().Legs.ToString());
}
}
어떻게 보면 DogMaker가 animalMaker에 값을 부여하는 것은 파생류가 기류에 값을 부여하는 것이 아니겠습니까?놀랄 게 뭐 있어. 사실 이곳의 주요 모순은 부치 호환성에 있는 것이 아니라
Factory
와Factory
는 같은 유형이 아니기 때문이야. Dog Maker와 animal Maker는 Dog과 Animal 종류가 아니야.여기서 DogMaker 에이전트의 함수는 Dog 대상을 되돌려주고 animalMaker 에이전트의 함수는 Animal 대상을 되돌려준다. 되돌려주는 값의 부여 호환성animalMaker = dogMaker
은 완전히 가능하다. 유일한 모순은 각각 Factory
과Factory
두 의뢰류에 속하는데 두 등급이 어떻게 서로 바뀌는지 사람과 개는 서로 바꿀 수 없다는 것이다(사람과 개는 모두 동물에 속하지만 != ( )
.이때 out 키워드는 관건적인 역할을 한다. out 키워드는 컴파일러에게 내가 가지고 있는 이 동생의 매개 변수는 출력에만 사용되는 것이니 Factory
와Factory
이 두 녀석은 상관하지 마라. 내가 데리고 있는 동생이 부치 호환성에 부합하기만 하면 된다.역변
class Animall {
public int NumberOfLegs = 4; }
class Dog : Animal{
}
class Program
{
delegate void Action <in T>(T a);
static void ActionAnimal(Animal a) {
Console.WriteLine(a.NumberOfLegs); }
static void main()
{
Action1<Animal> act1 = ActOnAnimal;
Action1<Dog> dog1 = act1;
dog1(new Dog());
}
}
static void ActionAnimal(Animal a) { Console.WriteLine(a.NumberOfLegs); }
이라는 코드를 보면 협변과 반대로 협변은 출력 매개 변수만 사용하는 것을 강조하는데 여기의Animal a는 어쩔 수 없이Console.WriteLine(a.NumberOfLegs);
에 사용되고 여기는 입력에만 사용된다.그래서 이 in 키워드는 관건적인 역할을 한다. 이것은 컴파일러에게 내가 데리고 있는 동생은 입력 매개 변수만 사용한다. 너는act1과dog1이 같은 유형이든 상관없다. 너는 이 두 의뢰 에이전트의 함수의 입력 매개 변수가 부수 호환성에 부합되는지 여부만 있으면 된다.총결산
인터넷에 이런 말이 있는데 나는 그다지 옳지 않다고 생각한다.
하위 클래스에서 하위 클래스로 변환하는 것은 협동 변환입니다. 반환값 형식에 사용되며 out 키워드로 하위 클래스에서 하위 클래스로 변환됩니다. 역변환 방법에 사용되는 매개 변수 형식은 in 키워드로 변환됩니다.
위의 두 단락의 코드를 보면 협동이든 역변이든 그 본질은 클래스의 부수 호환성에 부합되어야 한다.
Factory<Dog> dogMaker = MakeDog;
Factory<Animal> animalMaker = dogMaker;
Console.WriteLine(animalMaker().Legs.ToString());
dog1(new Dog()) = act1(new Dog())= ActOnAnimal(new Dog());
여기 new의 Dog는Animal로 전환되며 부치 호환성에 부합된다. Action1<Animal> act1 = ActOnAnimal;
Action1<Dog> dog1 = act1;
dog1(new Dog());
그리고 입력 매개 변수와 출력 매개 변수를 동시에 할 수 있을까요?다음 코드를 보십시오.
class Animal {
public int Legs = 4;}
class Dog : Animal {
}
delegate T Factory<T>(T t );
class Program
{
static Dog MakeDog(Dog dog)
{
Console.WriteLine($"{dog.legs}");
return new Dog();
}
static Animal MakeAnimal(Animal animal)
{
Console.WriteLine($"{animal.legs}");
return new Animal();
}
static void main()
{
Factory<Dog> dogMaker = MakeDog;
Factory<Animal> animalMaker = dogMaker;// Factory Factory
Factory<Animal> a = MakeAnimal;
Factory<Dog> b = a;// Factory Factory
Console.WriteLine(animalMaker().Legs.ToString());
}
}
이 코드는 컴파일을 통과할 수 없다. 이렇게 수정한 후에Factory가 의뢰한 범용 매개 변수 t는 입력 값과 반환 값을 한다. 이때 어느 쪽에서 어느 쪽에 값을 부여하든지 기본 클래스 대상이 파생 클래스 대상에게 값을 부여하는 난감한 장면을 만날 수 있다. 전송된 매개 변수가 아니라 되돌아오는 값에서 발생한다.이로써 아웃 (출력 매개 변수만) 과 in (입력 매개 변수만) 이라는 두 키워드가 왜 필요한지 알 수 있다. 왜냐하면 전환할 수 있다면 값 호환성에 부합해야 하기 때문이다.물론 이 두 키워드를 주지 않으면 부치 호환성에 딱 맞을까?나는 컴파일러가 그렇게 지능적이지 않다고 생각한다. 네가 그것을 알려주지 않았다면, 컴파일러는 판단할 수 없었을 것이다.
그런데 여기서 궁금한 게 하나 더 있어요. 아웃과 in으로 파라미터를 한정했어도
Factory
과Factory
는 같은 유형이 아니에요. 이 문제가 먼저 있어요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.