问题标签 [covariance]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
14 回答
76305 浏览

在 C# 中,为什么不能使用 List对象存储在列表中 variable

It seems that a List object cannot be stored in a List variable in C#, and can't even be explicitly cast that way.

List<string> sl = new List<string>();
Lis

It seems that a List object cannot be stored in a List variable in C#, and can't even be explicitly cast that way.

results in Cannot implicitly convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>

And then...

results in Cannot convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>

Of course, you can do it by pulling everything out of the string list and putting it back in one at a time, but it is a rather convoluted solution.


The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]

Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.

That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.

0 投票
3 回答
4700 浏览

继承需要存储子类特定数据的数组的最佳方法是什么?

我正在尝试设置类似于以下的继承层次结构:

我只想将 MotorcycleAxle 对象存储在 Motorcycle 对象的 Axles 数组中,并将 CarAxle 对象存储在 Car 对象的 Axles 数组中。问题是没有办法覆盖子类中的数组来强制其中一个。理想情况下,类似以下内容对 Motorcycle 类有效:

但是覆盖时类型必须匹配。我怎样才能支持这种架构?我是否只需要在访问 Axles 成员的任何地方进行大量运行时类型检查和转换?我不喜欢添加运行时类型检查,因为您开始失去强类型和多态性的好处。在这种情况下必须至少进行一些运行时检查,因为 WheelAttached 和 Left/RightWheelAttached 属性取决于类型,但我想最小化它们。

0 投票
17 回答
1180 浏览

为什么继承不能像我认为的那样工作?

我遇到了一些继承问题,因为我有一组相互关联的抽象类,需要一起重写以创建客户端实现。理想情况下,我想做以下事情:

这将允许任何使用 Dog 类的人自动获取 DogLegs 并允许任何使用 Animal 类的人获取 Legs。问题是被覆盖的函数必须与基类具有相同的类型,因此无法编译。我不明白为什么不应该这样做,因为 DogLeg 可以隐式转换为 Leg。我知道有很多方法可以解决这个问题,但我更好奇为什么这不可能/在 C# 中实现。

编辑:我对此进行了一些修改,因为我实际上是在代码中使用属性而不是函数。

编辑:我把它改回函数,因为答案只适用于那种情况(属性的 set 函数的 value 参数的协方差不应该起作用)。波动请见谅!我意识到这让很多答案看起来无关紧要。

0 投票
7 回答
605 浏览

哪些语言支持继承方法的返回类型的协变?

我最初问了这个问题,但在找到答案时,发现我最初的问题是 C# 中缺乏对继承方法的返回类型的协方差的支持。发现这一点后,我对哪些语言支持此功能感到好奇。

我会接受谁能说出最多名字的答案。

编辑:John Millikin 正确地指出许多动态语言都支持这一点。澄清:

我只是在寻找静态/强类型语言。

0 投票
9 回答
8630 浏览

获取向量进入一个需要向量的函数

考虑这些类。

这个函数

最后是我的矢量图

我想传递derived给 function BaseFoo,但编译器不让我。我如何解决这个问题,而不将整个向量复制到 a std::vector<Base*>

0 投票
9 回答
32118 浏览

我可以用派生类型覆盖吗?

据我所知,在 C# 2.0 中无法执行以下操作

我通过在派生类中将属性创建为“新”来解决该问题,但这当然不是多态的。

2.0有解决方案吗?3.5 中解决此问题的任何功能如何?

0 投票
5 回答
1819 浏览

有没有办法将通用列表转换为接口/基类类型列表?

我试图向某人展示在他们创造的疯狂情况下使用接口。它们在列表中有几个不相关的对象,并且需要对每个对象中的两个字符串属性执行操作。我要指出的是,如果他们将属性定义为接口的一部分,他们可以使用接口对象作为作用于它的方法参数的类型;例如:

这似乎一切都很好,但是需要处理的列表没有(也不应该)使用接口作为类型参数声明。但是,您似乎无法转换为不同的类型参数。例如,这失败了,我不明白为什么:

可以使用该Enumerable.Cast<T>成员来执行此操作,但我一直在寻找一种可能也适用于 .NET 2.0 的方法。看起来这应该是可能的;我错过了什么?

0 投票
7 回答
17665 浏览

如何将协变返回类型与智能指针一起使用?

我有这样的代码:

此代码无法编译。

在视觉工作室它提出

C2555:覆盖虚函数返回类型不同且不是协变的

如果我不使用boost::shared_ptr但返回原始指针,则代码编译(我理解这是由于 C++ 中的协变返回类型)。我可以看到问题是因为不是从boost::shared_ptrof派生的。但是我想返回用于其他类,否则我必须在返回后转换返回值。 Ret1boost::shared_ptrRetInterfaceboost::shared_ptrRet1

  1. 难道我做错了什么?
  2. 如果不是,为什么这种语言是这样的——在这种情况下处理智能指针之间的转换应该是可扩展的?是否有理想的解决方法?
0 投票
5 回答
2087 浏览

将子类的枚举数强制转换为父类的枚举数有错吗?

我的构建中有一个错误,上面写着:

错误 12 无法将类型“System.Collections.Generic.IEnumerator<BaseClass>”隐式转换为“System.Collections.Generic.IEnumerator<IParentClass>”。存在显式转换(您是否缺少演员表?)

简单地丢弃它是错误的吗?

这是我的代码:

我的问题是,我可以改变这一行:

到:

(没有任何不良副作用)?

接受的答案:
我已将功能更改为以下内容(阅读 Jon Skeet 的帖子后):

0 投票
2 回答
36636 浏览

C# 4.0 中如何实现泛型协方差和逆变换?

我没有参加 PDC 2008,但我听说 C# 4.0 宣布支持通用协变和逆变换的消息。也就是说,List<string>可以分配给List<object>。怎么可能?

在 Jon Skeet 的C# in Depth一书中,解释了为什么 C# 泛型不支持协变和逆变。它主要用于编写安全代码。现在,C# 4.0 更改为支持它们。会不会带来混乱?

有人知道有关 C# 4.0 的详细信息可以给出一些解释吗?