Kev*_*vin 5 c# inheritance delegates
我的代表似乎不接受一个子类,我认为一个例子是最简单的.
public class A
{
public A() { }
}
public class B : A
{
public B() { }
}
public class Program
{
private delegate void CallBack(A a);
private static CallBack callBack = new CallBack(Test);
public Main(string[] args)
{
callBack(new B());
}
private static void Test(A a)
{
Console.WriteLine("Test()");
}
// Compilation error occurs if Test becomes:
private static void Test(B a)
{
Console.WriteLine("Test()");
}
}
Run Code Online (Sandbox Code Playgroud)
当我更改Test以接受B它时会抛出编译错误.是不是因为B延伸A?
编译错误:
测试没有重载匹配回调
有没有办法让我的委托接受一个扩展的类A?
这不奇怪,因为B延伸A?
你有正确的想法,但方向错误.让我们考虑一个更容易推理的例子:
class Animal {}
class Reptile : Animal {}
class Snake : Reptile {}
class Mammal : Animal {}
class Tiger : Mammal {}
class Giraffe : Mammal {}
delegate void D(Mammal m);
static void DoAnimal(Animal a) {}
static void DoMammal(Mammal m) {}
static void DoTiger(Tiger t) {}
D dm = DoMammal;
dm(new Tiger());
Run Code Online (Sandbox Code Playgroud)
这显然是合法的.dm需要是一个采用哺乳动物的方法,而且它是.
D dt = DoTiger;
dt(new Giraffe());
Run Code Online (Sandbox Code Playgroud)
这显然是非法的.你不能指定一种方法将老虎带给一个哺乳动物的代表,因为一个哺乳动物的代表可以接受任何哺乳动物,而不仅仅是老虎.如果这是合法的,那么就可以将长颈鹿传递给一只需虎的方法.
那这个呢?
D da = DoAnimal;
da(new Giraffe());
Run Code Online (Sandbox Code Playgroud)
没关系.da是一种接受任何哺乳动物的方法的代表.一种明确摄取任何动物的方法也需要任何哺乳动物.您可以将DoAnimal(动物)分配给委托D(哺乳动物),因为Mammal扩展了Animal.你现在看到你如何向后延伸方向?
另一方面,返回类型以您认为的方式工作:
delegate Mammal F();
static Animal GetAnimal() {...}
static Mammal GetMammal() {...}
static Tiger GetTiger() {...}
F fm = GetMammal;
Mammal m = fm();
Run Code Online (Sandbox Code Playgroud)
没问题.
F ft = GetTiger;
Mammal t = ft();
Run Code Online (Sandbox Code Playgroud)
没问题; GetTiger返回一个Tiger,因此您可以将其分配给需要其目标返回哺乳动物的委托.
F fa = GetAnimal;
Mammal a = fa();
Run Code Online (Sandbox Code Playgroud)
那不好.GetAnimal可能会返回一个Snake,现在你有一个变量类型为Mammal,其中包含一个Snake.这必须是非法的.
此功能称为"成员组转换的协方差和逆变",它在C#2.0中引入.有关此主题的更多信息,请参阅我的文章:
这并不奇怪,因为如果您有一个Cextends类的对象A,Test()那么如果它只接受B. 用于 a 的任何方法都Callback必须接受任何 A,而不仅仅是特定的子类。如果您也想接受,则需要将Callback委托签名更改为接受。BTest()B
class C : A {};
Callback callback = Test;
callback(new C()); //what if Test() accepted B???
Run Code Online (Sandbox Code Playgroud)