当前位置: 首页 > 编程语言 > C#

Delegate不接受子类?分享

时间:2023-04-10 10:43:27 C#

Delegate不接受子类?我的代表似乎不接受子类,我认为一个例子是最简单的。publicclassA{publicA(){}}publicclassB:A{publicB(){}}publicclassProgram{privatedelegatevoidCallBack(Aa);privatestaticCallBackcallBack=newCallBack(测试);publicMain(string[]args){callBack(newB());}privatestaticvoidTest(Aa){Console.WriteLine("Test()");}//如果Test变成:privatestaticvoidTest(Ba){Console.WriteLine("Test()");就会出现编译错误当我将Test更改为接受B时,它会抛出编译错误。因为B扩展了A,这不是很奇怪吗?编译错误:测试不会重载匹配的回调有没有办法让我的委托接受扩展A的类?这并不奇怪,因为如果您有一个扩展A的类C的对象,如果它只接受B,则将它传递给Test()是没有意义的。用于回调的任何方法都必须接受任何A,而不仅仅是特定的子类。如果您希望Test()接受B您需要更改回调委托签名以接受BclassC:A{};回调回调=测试;回调(新C());//如果Test()接受B怎么办???因为B扩展了A,这不是很奇怪吗?你的想法是对的,但是方向错了。让我们考虑一个更容易推理的例子:classAnimal{}classReptile:Animal{}classSnake:Reptile{}classMammal:Animal{}classTiger:Mammal{}classGiraffe:Mammal{}delegatevoidD(Mammal米);staticvoidDoAnimal(动物a){}staticvoidDoMammal(哺乳动物m){}staticvoidDoTiger(老虎t){}Ddm=DoMammal;dm(新老虎());这显然是合法的。dm需要是一种采用哺乳动物的方法,它确实是。Ddt=DoTiger;dt(新长颈鹿());这显然是违法的。您不能指定将老虎带到哺乳动物代表处的方法,因为哺乳动物代表可以带走任何哺乳动物,而不仅仅是老虎。如果这是合法的,那么就有可能将长颈鹿传给老虎。这个如何?Dda=DoAnimal;大(新长颈鹿());没关系。da代表一种接受任何哺乳动物的方式。最终摄取任何动物的方法也需要任何哺乳动物。您可以将DoAnimal(animal)分配给委托D(mammal),因为Mammal扩展了Animal。您现在看到如何向后延伸方向了吗?另一方面,返回类型按照您认为的方式工作:delegateMammalF();staticAnimalGetAnimal(){...}staticMammalGetMammal(){...}staticTigerGetTiger(){...}Ffm=GetMammal;哺乳动物m=fm();没问题。Fft=GetTiger;哺乳动物t=ft();没问题;GetTiger返回一个Tiger,因此您可以将它分配给期望其目标返回一个Mammal的委托。Ffa=获取动物;哺乳动物a=fa();这不好。GetAnimal可能会返回一条Snake,现在您有一个包含Snake的Mammal类型的变量。这一定是违法的。此功能称为“成员组转换的协变和逆变”,它是在C#2.0中引入的。有关此主题的更多信息,请参阅我的文章:http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx这个很容易理解。现在我们有:classA{}classB:A{}场景1开始publicdelegatevoidCallBack(Aa);publicvoidTest(Aa){}CallBackcb=newCallBack(Test);cb(新A());//良好且简单的使用场景2CallBack(Aa)和Test(Bb)//编译错误,因为Test(Bb)的参数范围比CallBack//CallBackcb=newCallBack(Test);场景3回到CallBack(Bb)andTest(Aa)CallBackcb=newCallBack(Test);cb(新A());//没有报错,因为B可以转换为AC#代表支持协变和逆变,所以这个应该可以。问题是过载。//这个委托支持逆变——A的子类应该可以工作delegatevoidCallBack(Aa);//但是这不能选择任何一个Test,因为两者都可以使用staticCallBackcallBack=newCallBack(Test);在解析哪个重载方法签名(Test(Aa)或Test(Bb))时必须编译-但两者都可以应用,因此会抛出错误。您可以通过拆分重载来避免这种情况:staticvoidTestA(Aa){Console.WriteLine("Test(a)");}//如果Test变成:staticvoidTestB(Ba){Console.WriteLine("Test(b)");就会出现编译错误}//这是有效的,因为它是完全匹配的staticCallBackcallBackA=newCallBack(TestA);//这是有效的,因为委托支持逆变staticCallBackcallBackB=newCallBack(TestB);无论哪种情况,您都可以传递B://B是A的子类,因此可以传递给TestAcallBackA(newB());//CallBack支持逆变,所以可以调用TestBcallBackB(newB());鉴于你有这种反转,为什么你需要过载?以上就是C#学习教程:Delegate不接受子类?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: