委托不接受子类?

2024-04-12

我的委托似乎不接受子类,我认为一个例子是最简单的。

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()");
     }
 }

当我将测试更改为接受时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());

这显然是合法的。 dm 需要是一种采用哺乳动物的方法,而且确实如此。

D dt = DoTiger;
dt(new Giraffe());

这显然是违法的。您不能将捕获老虎的方法分配给捕获哺乳动物的委托,因为捕获哺乳动物的委托可以捕获任何哺乳动物,而不仅仅是老虎。如果这是合法的,那么就有可能将长颈鹿传递给老虎的方法。

那这个呢?

D da = DoAnimal;
da(new Giraffe());

没关系。 da 是接受任何哺乳动物的方法的代表。显然,适用于任何动物的方法也适用于任何哺乳动物。您可以将 DoAnimal(Animal) 分配给委托 D(Mammal),因为 Mammal 扩展了 Animal。现在您知道如何向后延伸的方向了吗?

返回类型另一方面,按照您认为的方式工作:

delegate Mammal F();
static Animal GetAnimal() {...}
static Mammal GetMammal() {...}
static Tiger GetTiger() {...}

F fm = GetMammal; 
Mammal m = fm();

那里没问题。

F ft = GetTiger;
Mammal t = ft();

没问题; GetTiger 返回一只老虎,因此您可以将其分配给要求其目标返回哺乳动物的委托。

F fa = GetAnimal;
Mammal a = fa();

那可不好。 GetAnimal 可能会返回一条 Snake,现在您有一个类型为 Mammal 的变量,其中包含一条 Snake。这一定是非法的。

此功能称为“成员组转换的协变和逆变”,在 C# 2.0 中引入。有关此主题的更多信息,请参阅我的文章:

https://ericlippert.com/2007/10/19/covariance-and-contravariance-in-c-part-3-method-group-conversion-variance/ https://ericlippert.com/2007/10/19/covariance-and-contravariance-in-c-part-3-method-group-conversion-variance/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

委托不接受子类? 的相关文章

随机推荐

  • Java中如何预加载类? [复制]

    这个问题在这里已经有答案了 在我的 Swing 界面中首次打开新的 JInternalFrame 需要一些时间 根据探查器 大部分时间都花在 Classloader loadClass 方法上 据我所知 它会在需要时动态加载类 并且实际上
  • 如何创建播放列表

    我正在尝试创建一个仅提供编辑文本和图像按钮的应用程序 如果单击按钮 则会将专辑添加到播放列表中 并在编辑文本框中命名 专辑应随机选择 不用说 专辑曲目应该按正确的顺序排列 我可以稍后添加更多功能 例如 保存 覆盖 删除等 我有界面 但正在努
  • Magento 1.9 注册后重定向客户

    我想在 Magento 1 9 中成功注册后将所有客户重定向到自定义页面 我已经尝试了很多事情 首先 我成功地覆盖了核心客户帐户控制器 我尝试自定义以下操作 创建后动作 successProcessRegistration welcome客
  • 在 C# 中实现动态 Web Scraper 的逻辑

    我希望在 C 窗口窗体中开发一个 Web scraper 我想要完成的任务如下 从用户处获取 URL 在WINForms中的IE UI控件 嵌入式浏览器 中加载网页 允许用户选择文本 连续 小 不超过 50 个字符 从加载的网页 当用户希望
  • 第三个克隆海龟

    我在尝试制作追逐游戏时制作了这个程序 但我偶然发现了一些非常奇怪的东西 我创建了海龟的克隆体 但在地图中间出现了第三个 有谁知道是什么原因造成的 import turtle sc turtle Screen t turtle Turtle
  • Java加密AES,PHP解密AES

    我正在寻找一种在 Java 中加密字符串并在 PHP 中解密的方法 我发现this http www logikdev com 2010 11 01 encrypt with php decrypt with java 在 Stackove
  • 阻止 Google Analytics 在开发环境、ASP.NET MVC 中收集数据

    我有一个 ASP NET MVC 3 应用程序 并且我已经设置了 Google 分析 问题是 每次我从 Visual Studio 运行时 Google 脚本都会开始收集数据 这当然会扭曲实际结果 阻止 Google Analytics 收
  • 本机客户端上用于 SMTP 的 Office 365 XOAUTH2 535 5.7.3 身份验证失败

    我尝试通过office 365的smtp发送邮件 我在azure中为本机客户端设置了应用程序注册并设置了权限SMTP Send 但是当我连接时 我已经能够获得令牌 但发送不起作用 在我阅读的所有其他文章中 我需要设置 https outlo
  • 无法创建类型的常量值在此上下文中仅支持基本类型或枚举类型

    我在下面的查询中收到此错误 无法创建类型的常量值API Models PersonProtocol 此上下文中仅支持基本类型或枚举类型 ppCombined下面是一个IEnumerable的对象PersonProtocolType 由 2
  • Firebase 身份验证 - 开源 Android 应用

    有没有办法Firebase 身份验证 https firebase google com docs auth gclid EAIaIQobChMIhKuIo zV4wIVhRx9Ch1VwAh7EAAYASAAEgLRrvD BwE在开源应
  • SQLAlchemy 查询 API 在提示下无法正常工作

    我正在尝试使用查询 API 创建带有 MAX EXECUTION TIME 30000 提示的 MySQL 查询 我的代码大致是 from flask sqlalchemy import SQLAlchemy class MyTable S
  • 为什么我可以转换为 NSManagedObject 但不能转换为我的实体的类型?

    我在一个新项目中使用 Core Data 的 Swift 样板代码 我的 xcdatamodeld文件定义了一个实体 Task 具有单个属性 name 我有一个Task swift文件看起来像这样 import CoreData class
  • 用于 RHEL 的 gdb-multiarch

    我正在尝试寻找方法来运行gdb 多架构RHEL 中的命令 我已经安装了用于 ARM 处理的 QEMU 模拟器 我想安装GDB进行调试 我能够安装GDB 多体系结构在 Ubuntu 中运行命令成功 sudo apt get GDB multi
  • CSS:如何使盒子内部的角变圆? [复制]

    这个问题在这里已经有答案了 有border radius属性为圆形框角 但是如何在块内圆角 例如减去圆 像这儿 http malsup com jquery corner http malsup com jquery corner 卷曲设置
  • preg_match_all() 在不同的服务器上表现不同

    下面的代码在我的 PC 上的 XAMPP 上运行完美 但在我新购买的 VPS 上不起作用 它使我的代码崩溃了 preg match all regex siU string matches PREG SET ORDER 这预计只是从 HTM
  • 如何从 Android 中的自定义 CameraView 捕获图像?

    我需要捕捉图像 from 所需部分 of the screen 捕捉图像 from camera 当时其他屏幕内容保持原样 这怎么样possible 尝试使用表面视图 for 创造动态 camera查看并设置您需要的部分 下面的代码尝试 变
  • 从 pthread 调用 sleep() 是否会使线程或进程进入睡眠状态?

    我看到有一个关于linux pthread睡眠 https stackoverflow com questions 3633089 pthread sleep linux 然而 当我在 Linux 机器上查找手册页时 我看到以下内容 概要
  • 在 Mac OS X 的 Swing 应用程序中嵌入 JRE

    我必须发布带有嵌入式 JRE 的 swing 应用程序 包含应用程序 JRE bat sh 的压缩存档可以在 Windows 和 Linux 上实现 用户下载 zip 文件 解压缩并启动应用程序 完美的 但现在 我必须为 Mac OS X
  • Angular 7 组件测试使用原始服务而不是模拟服务

    我正在尝试测试具有注入服务的组件 我想在我的测试中提供模拟服务 然而 测试使用原始服务而不是模拟服务 我知道这一点是因为我收到 没有 HttpClient 的提供程序 错误 而且我在测试中输出的原始服务中有一个 console log 我可
  • 委托不接受子类?

    我的委托似乎不接受子类 我认为一个例子是最简单的 public class A public A public class B A public B public class Program private delegate void Ca