C# 数组的协变和逆变 [重复]

2024-02-15

在阅读一本section http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Arrays在维基百科上一篇关于协变和逆变的文章中,我遇到了以下粗体句子:

首先考虑数组类型构造函数:来自类型Animal我们可以制作类型Animal[](“动物阵列”)。我们是否应该将其视为

  • 协变:aCat[] is a Animal[]
  • 逆变:aAnimal[] is a Cat[]
  • 或两者都不是(不变)?

如果我们希望避免类型错误,并且数组支持读取和写入元素,那么只有第三种选择是安全的。显然,并非每一个Animal[]可以被视为一个Cat[],因为从数组中读取的客户端会期望一个 Cat,但是一个Animal[]可能包含例如ADog。所以逆变规则并不安全。

相反,一个Cat[]不能被视为Animal[].应该总是可以放置一个Dog into a Animal[]。对于协变数组,这不能保证安全,因为后备存储实际上可能是猫的数组。所以协变规则也不安全——数组构造函数应该是不变的。请注意,这只是可变数组的问题;协变规则对于不可变(只读)数组是安全的。

我理解这个概念;我只想要一个example说明 C# 中如何“不能保证安全”。


这不安全在编译时。换句话说,有些代码根据语言规则是合法的,但在执行时失败,没有任何显式转换来给出“这可能会失败”的大警告信号。 CLR 确保只有有效的写入才能成功执行时间。例如:

string[] strings = new string[1];
object[] objects = strings;
objects[0] = new object();

这将引发异常(ArrayTypeMismatchException https://learn.microsoft.com/en-us/dotnet/api/system.arraytypemismatchexception) 在执行时。另一种选择是allow它在执行时,此时strings[0]将是对非字符串对象的引用,这显然是不好的。

另请参阅最近的博客文章:

  • 我的一份 https://codeblog.jonskeet.uk/2013/06/22/array-covariance-not-just-ugly-but-slow-too/关于使用通用包装器的性能和安全性
  • 一是关于不可变数组 https://devblogs.microsoft.com/dotnet/please-welcome-immutablearrayt/来自 BCL 团队
  • Eric Lippert 关于一般方差的博客系列的第 2 部分 https://learn.microsoft.com/en-us/archive/blogs/ericlippert/covariance-and-contravariance-in-c-part-two-array-covariance(该系列主要针对泛型,但这部分是关于数组的)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 数组的协变和逆变 [重复] 的相关文章

随机推荐

  • 了解 CComBSTR 赋值运算符

    假设我有以下内容 BSTR myBSTR SysAllocString L MYBSTR CComBSTR myCComBSTR myBSTR Does myCComBSTR取得所有权myBSTR当它超出范围时释放它 或者它是否复制了myB
  • 无法加载动态库“libcublasLt.so.11”; dlerror: libcublasLt.so.11: 无法打开共享对象文件: 没有这样的文件或目录

    我刚刚更新了我的显卡驱动器 sudo apt install nvidia driver 470 sudo apt install cuda drivers 470 我决定以这种方式安装它们 因为它们在尝试安装时受到阻碍sudo apt u
  • 在C中获取文件扩展名

    如何获得文件扩展名 例如 tiff 来自 C 中的文件名 Thanks const char get filename ext const char filename const char dot strrchr filename if d
  • 从 url 不变的网站中抓取响应表

    我希望从该网站抓取价格历史记录 单击价格历史记录按钮后 表格将被加载 但网址保持不变 我想刮掉桌子上的负载 import requests from bs4 import BeautifulSoup rr requests get url
  • Angular4:用户的区域设置

    我想要一个登录表单 并在该用户输入应用程序后 使用德语或英语使用 据我了解 我可以设置app module ts就像是 import LOCALE ID from angular core providers provide LOCALE
  • 使用 iTextSharp 设置页边距

    我有一个 PDF 模板文件 其中嵌入了一个 PDF 表单字段 我正在使用 PdfStamper 来填写这些字段 此外 我希望能够更改生成的 PDF 的边距 有什么方法可以修改已盖章的 PDF 上的页边距吗 您可以在一行中完成所有操作 Doc
  • 导入文本文件时跳过空文件

    我有一个包含大约 700 个文本文件的文件夹 我想要导入这些文件并向其中添加一列 我已经弄清楚如何使用以下代码来做到这一点 files list files pattern c txt DF lt NULL for f in files d
  • Pandas 交叉表和计数

    我正在使用 Python 熊猫 我有一个带有字符串的列 我想在列之间进行交叉 例如我有以下输入 1 Andi 2 Andi Cindy 3 Thomas Cindy 4 Cindy Thomas 我想要以下输出 因此 安迪和托马斯的组合没有
  • Scala 参与者与非参与者交互(或将消息从参与者同步到 servlet)

    我有以下 scala 代码 package dummy import javax servlet http HttpServlet HttpServletRequest gt HSReq HttpServletResponse gt HSR
  • 异常在构造函数 try 块中捕获并处理,但仍会再次重新抛出

    我试图更好地理解处理继承时的抛出 捕获机制 我试图解决的问题是 如果在构造派生类时 首先构造的基类抛出异常 将会发生什么情况 include
  • CSS Margin: 0 未设置为 0

    我是网页设计的新手 我使用 CSS 和 HTML 创建了网页布局 如下所示 问题是 即使我将边距设置为 0 上边距也没有设置为 0 并留下了一些空间 我怎样才能清除这个空白区域 问题的屏幕截图 样式表
  • 使用 php 为 apache 日志设置 REMOTE_USER

    在 mod perl 中我可以做类似的事情 r gt user username 然后用户名将显示在日志的用户名部分中 有没有办法在 php 中做到这一点 无需修改apache Edit 到目前为止我已经尝试过两种 SERVER REMOT
  • 为什么 string.split() 结果包含未定义?

    我想在其中一个上分割一个字符串 d or n 我能够成功地分割这两者之一 但不能同时分割 gt msg foo 1 bar n baz 2 gt msg split d foo 1 bar baz 2 gt msg split n foo
  • 在 POST 负载中使用环境变量

    我可以在我发布的有效负载中使用先前测试中设置的环境变量吗 eg POST list some key environment saved value 是的 你可以这么做 你这样发送 some key environment variable
  • Python print 语句在参数之间添加空格

    我正在编写一个非常基本的 hello 程序 但我在名称和第一个感叹号之间不断出现空格 而我在代码中没有看到该空格 我尝试用几种不同的方式重新格式化字符串部分来连接间距 但我无法弄清楚是什么导致了额外的空间 我尝试过单独使用感叹号 或者将其作
  • 在 CUDA 内核中声明变量

    假设您在 CUDA 内核中声明一个新变量 然后在多个线程中使用它 例如 global void kernel float delt float deltb int i blockIdx x blockDim x threadIdx x fl
  • 为数据类型定义自己的 Ord

    我正在尝试制作一些数据结构来解决图形难题 我正在尝试定义边缘的比较标准 但我不确定如何定义 迄今为止 data Edge Edge Set String Bool 如果边缘具有相同的字符串集 并且相等与布尔值没有任何关系 我如何 通知 编译
  • unordered_map 具有三个元素

    我试图在一个元素中包含三个元素unordered map 我尝试了以下代码 include
  • 如何解除对 Java 启动进程的阻止?

    当从命令行执行某些命令 比如说 x 时 我收到以下消息 按任意键继续 因此它会等待用户输入来解锁 但是当我从 java 执行相同的命令 x 时 Process p Runtime getRuntime exec cmd null cmdDi
  • C# 数组的协变和逆变 [重复]

    这个问题在这里已经有答案了 在阅读一本section http en wikipedia org wiki Covariance and contravariance 28computer science 29 Arrays在维基百科上一篇