问题标签 [contravariance]

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 投票
3 回答
4700 浏览

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

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

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

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

0 投票
17 回答
1180 浏览

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

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

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

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

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

0 投票
2 回答
36636 浏览

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

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

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

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

0 投票
5 回答
1914 浏览

c# - 为什么我们需要 C# 中协变和逆变的新关键字?

有人可以解释为什么需要添加 out 或 in 参数来指示泛型类型是 C# 4.0 中的 Co 或 Contra 变体吗?

我一直在试图理解为什么这很重要以及为什么编译器不能弄清楚..

谢谢,

乔什

0 投票
4 回答
3287 浏览

class - 关于类继承的协变与逆变

“协变”和“逆变”这两个概念的含义是什么?

给定 2 个类AnimalElephant(从Animal继承),我的理解是,如果您尝试将 Elephant 放入 Animals 数组中,您会遇到运行时错误,这是因为 Elephant 是“更大”(更多具体)比动物。但是,您能否将 Animal 放入 Elephant 数组中,看看 Elephant 是如何保证包含 Animal 属性的?

0 投票
5 回答
15984 浏览

c# - 从 IEnumerable 强制转换 to IEnumerable

Recently I found a very surprising behavior in c#. I had a method which takes IEnumerable<Object> as a parameter and i was passing IEnumerable<string>

Recently I found a very surprising behavior in c#. I had a method which takes IEnumerable<Object> as a parameter and i was passing IEnumerable<string> but it's not possible. While in c# everything can be upcast to Object than why this is not possible? It's totally confusing for me. Please someone clear me on this issue.


The technical term for this is that generics are invariant in C# 3.0 and earlier. From C#4.0 onward, the cast works.

What invariant means is that there is no relationship between two generic types just because their generic type parameters are related (i.e. are sub- or supertypes of each other).

In your example, there is no typing relationship between an IEnumerable<object> and an IEnumerable<string>, just because string is a subtype of object. They're just considered two completely unrelated types, like a string and an int (they still both are subtypes of object, but everything is)

There are a few workarounds and exceptions for this issue you've run into.

First, you can cast each string individually to object, if you're using .NET 3.0 you can do that using the Cast<T>() extension method. Otherwise, you can use a foreach and put the result into a new variable of the static type you want.

Second, arrays are an exception for reference type, i.e. passing in a string[] type to a method acccepting object[] types should work.

0 投票
6 回答
4880 浏览

java - 覆盖 Java 泛型方法

我想创建一个用于将对象复制到同一类的目标对象的接口。简单的方法是使用强制转换:

但我也找到了一种可以使用泛型完成的方法:

虽然我发现摆脱警告的唯一方法是注释。而且感觉好像出了点问题。那么有什么问题呢?我可以接受问题的根源有问题。因此,欢迎任何形式的澄清。

0 投票
1 回答
14690 浏览

java - Scala中变量声明中的通用通配符

在 Java 中,我可能会这样做:

...假设(MyImpl implements MyInterface)当然。

使用Scala中的类似物是Buffer什么?

这(当然)不会编译 - 但是我如何list以这样的方式声明变量呢?

编辑;我再补充一点。区别显然与以下事实有关:在 Java 中,泛型在 T 中永远不会协变,而在 Scala 中,它们可以是协变的,也可以不是协变的。例如,Scala 类List在 T 中是协变的(并且必然是不可变的)。因此以下将编译

我仍然在为编译器错误苦苦挣扎:

Covariant type T occurs in contravariant position in ...

例如; 此编译器错误发生在类声明中:

我要问一个单独的问题...

0 投票
4 回答
31815 浏览

generics - 为什么示例不编译,也就是(co-,contra-和in-)方差如何工作?

this question之后,有人可以在Scala中解释以下内容:

+T我理解类型声明中和之间的区别T(如果我使用它会编译T)。但是,如何在不诉诸于创建未参数化的事物的情况下,实际编写一个类型参数协变的?如何确保只能使用 的实例创建以下内容T

编辑-现在将其归结为以下内容:

这一切都很好,但我现在有两个类型参数,我只想要一个。我将重新提出这个问题:

如何编写一个类型协变的不可变 Slot类?

编辑2:呃!我用过var,没有val。以下是我想要的:

0 投票
2 回答
192 浏览

c#-3.0 - 我应该在 C#3.0 中支持 Pub-/Sub-Scenarios 的 Co-/Contravariance 吗?

在我的应用程序中,我正在创建一个简单的事件中心,它为注册订阅者提供了一些东西:

并用于发布事件。

非常简单。我想路由Publish<int>(0)到所有实现的订阅者ISubscriber<int>.

不太难的是,我希望订阅者 EventType 是逆变的。所以ISubscriber<object>基本上应该消耗掉一切。我不希望他们也使用值类型。

用 C#4 没问题,但现在我用 C#3 做这些事情,只是用接口假装逆变:

好吧,现在,我想像这样将数据打包成“事件类型”。该事件的通用参数必须是协变的。

当我发布Publish<DataChanged<B>>(new DataChanged<B>(new B())(给定 B:A)时,应通知订阅者DataChanged<A>Data 是传递给的 B 实例的位置DataChanged<B>。所以我也需要协方差支持。

我想编写一个支持 Co-/和逆变的库,如下所示:

这将允许像这样的转换(不是强制转换!):

你怎么看?可能吗?考虑使用动态代理来做这件事。