问题标签 [generic-variance]

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 投票
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 投票
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 投票
2 回答
424 浏览

c# - 类层次结构问题(具有泛型的差异!)

问题:

假设IList返回的是只读的,我知道我想要实现的是安全的(或者不是?)。有什么办法可以完成我正在尝试的事情吗?我不想尝试自己实现TasksChain算法(再次!),因为它容易出错并且会导致代码重复。也许我可以定义一个抽象链,然后从那里实现TasksChain两者StatesChain?或者也许实现一个Chain<T>类?

您将如何处理这种情况?

详细信息: 我定义了一个ITask接口:

和一个IState继承自的接口ITask

我还定义了一个IHasTasksList接口:

和一个IHasStatesList

现在,我定义了一个TasksChain,这是一个具有一些代码逻辑的类,可以操作一系列任务(请注意,TasksChain它本身就是一种ITask!):

我正在实施State以下方式:

如您所见,它使用显式接口实现来“隐藏”FailureTask而不是显示FailureState属性。

问题来自这样一个事实,即我还想定义 a StatesChain,它继承自IStateand IHasStateList(并且它也实现ITaskand IHasTaskList,实现为显式接口)并且我希望它也隐藏IHasTaskList'sTasks并且只显示IHasStateList's States(“问题”部分中包含的内容应该在此之后,但我认为把它放在第一位会更便于读者阅读)。

(pff..长文本)谢谢!

0 投票
1 回答
717 浏览

c# - C# Delegate under the hood 问题

在阅读了 SO 中的以下问题后,我正在研究委托差异:Delegate.CreateDelegate() and generics: Error binding to target method

我在https://www.blogger.com/comment.g?blogID=8184237816669520763&postID=2109708553230166434从 Barry kelly 那里找到了一段非常好的代码

在这里(以糖化形式:-)

除了这一行(看起来很简单)之外,我都了解。

b = a.调用;// 使用方差分配委托的简单方法,虽然增加了间接层

谁能告诉我:

  1. 如何在不传递静态函数所需的参数的情况下调用调用。
  2. 当您从调用调用分配返回值时,何时在幕后发生
  3. 巴里所说的额外间接是什么意思(在他的评论中)
0 投票
1 回答
1530 浏览

c#-4.0 - 使用懒惰的问题从通用抽象类中

我有一个泛型类,我的所有 DAO 类都从该类派生,定义如下。我的所有实体也都有一个基类,但这不是通用的。

该方法GetIdOrSave将与我定义的类型不同SabaAbstractDAO,因为我试图获取主键来满足外键关系,所以这个函数要么获取主键,要么保存实体,然后获取主键钥匙。

最后一个代码片段有一个解决方案,如果我去掉通用部分,它将如何工作,所以我认为这可以通过使用方差来解决,但我不知道如何编写一个可以编译的接口。

当我尝试编译时出现此错误:

我试图这样称呼它:

如果我将定义更改为此,它会起作用。

那么,如何使用方差(如果需要)和泛型来编译它,这样我就可以有一个非常通用的方法,只适用于BaseModeland AbstractDAO<BaseModel>?我希望我只需要在方法和抽象类定义中进行更改,用法应该没问题。

更新: 有一个非常有用的回应,我有一个稍微改进的例子,但一个有趣的困境:

我现在已经定义了这个,并且我没有任何inor outon T这里因为我得到了矛盾的错误,如果out T我得到它必须是contravariantly valid并且如果in Tthen covariantly valid,所以我使它保持不变,因为它似乎 VS2010 无法计算出来。

我收到此错误,尽管它确实编译了:

我修复了上面的两个代码片段,但似乎方差不会像我希望的那样起作用。

我试过这个:

但是我遇到了与界面相同的问题,如果我把out它抱怨,那么我就提出in了相反的抱怨。

如果这是合法的,我想我可以让它工作:

0 投票
1 回答
609 浏览

scala - 如何确定类型参数的方差?

受到Scala中协变和逆变的真实示例的启发,我认为一个更好的问题是:

在设计库时,在确定类型参数应该是协变还是逆变时,是否应该问自己一组特定的问题?还是应该让所有内容保持不变,然后根据需要进行更改?

0 投票
3 回答
2009 浏览

c# - 自定义 Autofac 的组件分辨率/具有通用协变/逆变的问题

首先,对于模糊的问题标题感到抱歉。我想不出更精确的。

鉴于这些类型:

我想编写一个Dispatch接受任何命令并将其发送到适当的ICommandHandler<>. 我认为使用 DI 容器(Autofac)可能会大大简化从命令类型到命令处理程序的映射:

假设 DI 容器知道上面显示的所有类型。现在我打电话给:

实际上,这将导致 Autofac 抛出 a ComponentNotRegisteredException,因为没有ICommandHandler<SpecialFooCommand>可用的。

然而,理想情况下,我仍然希望 aSpecialFooCommand由可用的最匹配的命令处理程序处理,即。上面例子中的 a FooCommandHandler

是否可以为此定制 Autofac,也许使用自定义注册源?


PS:我知道可能存在阻碍协变/逆变的基本问题(如下例所示),唯一的解决方案可能是根本不使用泛型的解决方案......但我会如果可能的话,想坚持使用泛型类型。

0 投票
3 回答
1229 浏览

c++ - C ++中的泛型JAVA?怎么做?

我的代码有什么问题..输出如下...

1>链接...
1>TemplateStuding1.obj:错误LNK2001:无法解析的外部符号“class X __cdecl doIt(class X)”(??$doIt@VXClass@@@@YA?AVXClass@@V0@@Z)
1 >D:\Programming\cpp\cpp-how-to-program\CppHowToProgram\Release\Test.exe : 致命错误 LNK1120: 1 unresolved externals

0 投票
2 回答
768 浏览

c# - 为什么我可以转换 IList 的不变性离开?

目前,我正在为我的同事准备 C# 中新的通用方差特性的演示文稿。简而言之,我写了以下几行:

是的,这当然是不可能的,因为 IList(Of T) 是不变的(至少我的想法)。编译器告诉我:

无法将类型隐式转换 System.Collections.Generic.IList<System.Windows.Forms.Form>System.Collections.Generic.IList<System.Windows.Forms.Control>. 存在显式转换(您是否缺少演员表?)

嗯,这是否意味着我可以强制进行显式转换?我刚试过:

而且......它编译!这是否意味着我可以抛弃不变性?- 至少编译器可以接受,但我只是将以前的编译时错误变成了运行时错误:

Unable to cast object of type 'System.Collections.Generic.List`1[System.Windows.Forms.Form]' to type 'System.Collections.Generic.IList`1[System.Windows.Forms.Control]'.

我的问题:为什么我可以抛弃IList<T>(或任何其他关于我的实验的不变接口)的不变性?我真的抛弃了不变性,或者这里发生了什么样的转换(因为IList(Of Form)并且IList(Of Control)完全不相关)?这是我不知道的 C# 的一个黑暗角落吗?

0 投票
2 回答
887 浏览

c# - 多泛型歧义

下面的代码完全一样,只是一个是C#,另一个是VB.Net。C# 编译得很好,但 VB.Net 抛出警告:

由于 'Interface IObserver(Of In T)' 中的 'In' 和 'Out' 参数,接口 'System.IObserver(Of Foo)' 与另一个实现的接口 'System.IObserver(Of Bar)' 不明确

为什么 VB.Net 显示警告而不是 C#?最重要的是,我该如何解决这个问题?

Obs:我正在使用 .Net Framework 4 和 Visual Studio 2010 Ultimate。

VB.Net 代码:

C#代码: