问题标签 [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 投票
5 回答
5326 浏览

c# - 了解 C# 4.0 中的协变和逆变

我在第 9 频道观看了有关它的视频,但我并没有真正理解它。

有人可以给我一个简单易懂的例子吗?在那之后,它可能会如何在实践中使用?

0 投票
2 回答
254 浏览

java - 在编译器或类型检查器 (javac) 中导致堆栈溢出的 Java 片段?

昨天在一次研讨会上,演讲者 (Peter Sestoft) 展示了一个小型 java 程序,有 3 个类,同时具有协变和逆变。尝试使用 javac 编译时,类型检查器将抛出 StackOverflowException。

该片段是由一些在微软工作的人开发的(想想一个叫做肯尼迪)。

用谷歌找不到。有谁知道代码片段,你能把它贴在这里(最多10行代码)给大家看吗?:)

这很有趣……

0 投票
2 回答
751 浏览

c# - C# 3 中具有接口继承(co(ntra)-variance?)的泛型类型推断

我有以下两种通用类型:

现在我想为这些接口的集合定义一个扩展方法,因为它们都是或者是它们的IRange<T>后代,IRange<T>我希望我可以定义一个可以处理这两者的方法。请注意,该方法不需要处理两者之间的任何差异,只需处理来自IRange<T>.

我的问题是这样的:

我可以定义一个扩展方法来处理IEnumerable<T>这两种类型中的任何一种的集合()吗?

我试过这个:

然而,传递一个IEnumerable<IRange<Int32, String>>,像这样:

给了我这个编译器错误:

错误 1“System.Collections.Generic.IEnumerable>”不包含“Slice”的定义,并且找不到接受“System.Collections.Generic.IEnumerable>”类型的第一个参数的扩展方法“Slice”(你是缺少 using 指令或程序集引用?) C:\Dev\VS.NET\LVK\LVK.UnitTests\Core\Collections\RangeTests.cs 455 26 LVK.UnitTests

注意:我没想到它会编译。我对 co(ntra)-variance 有足够的了解(总有一天我需要知道哪个是哪个方式)知道那是行不通的。我的问题是我是否可以对 Slice 声明做任何事情以使其发挥作用。

好的,然后我尝试推断范围接口的类型,这样我就可以处理所有类型,IEnumerable<R>只要有R问题是IRange<T>.

所以我尝试了这个:

这给了我同样的问题。

那么,有没有办法调整这个?

如果没有,我唯一的选择是:

  1. 定义两个扩展方法,并在内部调用一个内部方法,可能是通过将其中一个集合转换为包含基本接口的集合?
  2. 等待 C# 4.0?

以下是我设想定义这两种方法的方式(注意,我仍处于早期设计阶段,所以这可能根本不起作用):


这是一个显示我的问题的示例程序代码。

请注意,通过在 Main 方法中将调用从 Slice1 更改为 Slice2 会使两种用法都产生编译器错误,因此我的第二次尝试甚至没有处理我最初的情况。

0 投票
5 回答
21457 浏览

c# - 逆变解释

首先,我已经阅读了许多关于 SO 的解释以及关于协变和逆变的博客,非常感谢Eric Lippert制作了这么多关于变和逆变的系列。

但是,我有一个更具体的问题,我想稍微了解一下。

据我了解,Eric 的解释是 Covariance 和 Contravariance 都是描述转换的形容词。协变变换是保留类型顺序的变换,而逆变变换是反转它的变换。

我以我认为大多数开发人员直观理解的方式理解协方差。

这里的返回操作是协变的,因为我们保留了两个 Animal 仍然大于 Mammal 或 Giraffe 的大小。关于这一点,大多数返回操作都是协变的,逆变操作没有意义。

对于大多数开发人员来说,这段代码当然没有意义。

我的困惑在于逆变参数参数。如果你有一个方法,比如

我一直都知道输入参数总是强制逆变行为。这样,如果将类型用作输入参数,则其行为应该是逆变的。

但是下面的代码有什么区别

出于同样的原因,你不能做这样的事情你不能做

我想我要问的是,是什么让方法参数通过逆变转换。

对不起,很长的帖子,也许我理解错了。

编辑:

根据下面的一些对话,我了解例如使用委托层可以清楚地显示逆变性。考虑以下示例

当然这是非法的,因为有人可以将任何 Animal 传递给 someAction,而 ProcessMammal 期望任何是 Mammal 或更具体(小于 Mammal)的东西。这就是为什么 someAction 只能是 Action 或更具体的 (Action)

然而,这在中间引入了一层代表,为了实现逆变投影,是否必须在中间有一个代表?如果我们将 Process 定义为一个接口,我们会将参数参数声明为逆变类型,只是因为我们不希望有人能够做我上面展示的委托?

0 投票
6 回答
33447 浏览

c# - 协方差和反方差之间的区别

我无法理解协方差和逆变之间的区别。

0 投票
3 回答
3313 浏览

.net-4.0 - C# 4.0 中的泛型变体

C# 4.0 中的 Generic Variance 的实现方式使得可以毫无例外地编写以下内容(这在 C# 3.0 中会发生):

[示例非功能性:参见 Jon Skeet 的回答]

我最近参加了一个会议,Jon Skeet 对通用方差进行了出色的概述,但我不确定我是否完全理解它 - 我理解inout关键字在反方差和协方差方面的重要性,但我很好奇幕后发生的事情。

执行此代码时,CLR 会看到什么?它是隐式转换List<int>List<object>还是简单地内置,我们现在可以在派生类型之间转换为父类型?

出于兴趣,为什么在以前的版本中没有引入它,主要的好处是什么 - 即现实世界的使用?

有关通用差异的这篇文章的更多信息(但问题非常过时,正在寻找真实的最新信息)

0 投票
1 回答
365 浏览

c# - 协变、逆变和委托问题

我再次需要你的帮助,这一次我在协变、逆变、委托和一个简单的想法爆炸中挣扎......

我想为我们的 businessobject-properties 实现一个属性,该属性接受一个委托和该委托所需的参数,以便我可以使用反射、读出属性并对属性值执行验证。

这背后的原因是,我们正在使用带有 DataBinding 的 Windows.Forms,并且需要将 DataBinding 更新方法设置为 OnPropertyChanged,以在 GUI 上获得正常工作的刷新。然而,我们确实需要一种在控件的验证事件中做出反应以正确验证属性的方法,以查看用户是否可以实际保存对象。但是控件的 Validating-Event 仅在将值写入属性后才会发生。在属性的设置器中进行验证会导致崩溃,并且我们无法向用户提供确切的信息,除非我们第二次实施验证(或将其提取到从设置器调用的方法中)。

为了保持这个最优雅和干净,我认为拥有以下之一会很不错:

这样我就可以通过反射对所有属性进行迭代,执行我们希望它们执行的所有验证,并使用正确的方法设置 PropertyValidator-Attribute。但是我对这个想法进行了一些尝试,但无论如何都没有让它发挥作用,这就是我所拥有的,可能你对如何实现这一点有一个想法。

欢迎任何提示...

0 投票
4 回答
537 浏览

c# - 实例化参数化类型列表,更好地利用泛型和 Linq

我正在使用一种或多种哈希算法对文件进行哈希处理。当我尝试参数化我想要的哈希类型时,它比我希望的要混乱得多。

我想我错过了更好地利用泛型或 LINQ 的机会。我也不喜欢我必须使用 Type[] 作为参数,而不是将其限制为更具体的一组类型(HashAlgorithm 后代),我想将类型指定为参数并让此方法执行构造,但如果我让调用者新的 HashAlgorithm 实例传入,这可能看起来会更好?

0 投票
3 回答
45363 浏览

java - 给出在 Java 中重载和覆盖的情况下演示协变和逆变的函数示例?

请举一个Java中协变和逆变的好例子。

0 投票
6 回答
975 浏览

c# - 为什么在实现接口的方法时可以应用“协变”和“逆变”的概念?

用例是这样的:

现在我的问题是,如果我们考虑协方差和逆变的基础,为什么不能使用“SomeClass(因为它是从对象派生的)”作为 Clone() 方法的返回类型

有人可以解释一下微软这个实现背后的原因吗????