问题标签 [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 回答
198 浏览

c# - C# 4.0 变体可以帮助我调用带有向上转换的基类构造函数吗?

我正在阅读一些关于通用方差的内容,但我还没有完全理解它,但我想知道它是否使以下内容成为可能?

0 投票
1 回答
2160 浏览

c# - 将 List(of List(of MyType)) 转换为 IEnumerable(of IEnumerable(of MyType))

我有一个接受类型参数的方法IEnumerable(Of IEnumerable(Of MyType))

如果我执行以下操作:

有用。

如果我通过 aList(Of List(Of MyType))它编译但给出运行时错误,如下所示:

如果我通过MyType()()它会给出编译时错误,如下所示:

我目前正在使用.net 3.5。

这似乎是一个类似于Casting List<MyObject> to IEnumerable<MyInterface>的问题,我听说在 .net 4 中已解决。

有什么想法可以避免这个错误吗?

0 投票
2 回答
346 浏览

c# - IDictionary 上的单一扩展方法>

我正在尝试编写一个扩展方法,它将IDictionary<K, S<V>>持有任何类型的集合/序列(S<V>)转换ILookup<K, V>为在这些情况下更合适的数据结构。这意味着我希望我的扩展能够在不同的S类型和接口上工作:

  • IDictionary<K, IEnumerable<V>>
  • IDictionary<K, ICollection<V>>
  • IDictionary<K, List<V>>

等理想情况下,我不想为每个可能的集合类型编写单独的实现,我希望类型推断能够完成它的工作。

我试过的是:

但它TValue在参数列表中没有,因此类型推断无法弄清楚 - 我得到“方法 ToLookup 的类型参数无法从用法中推断出来”。

TValue除了在方法中添加 fake -typed 参数之外,它是否有可能以其他方式工作?

预期用法示例

我希望上述所有调用都是可能的,并导致调用我的单个扩展方法:

0 投票
0 回答
113 浏览

c# - 涉及泛型类型参数的运行时强制转换

我正在构建一个命令调度函数,这样给定一个派生自基类的对象,它会(从 IoC 容器)解析命令类型的处理程序并将命令对象发送到那里进行处理。我的类型如下所示:

示例实现:

当我接到电话时,我可以(几乎)从我的容器中检索匹配的处理程序,如下所示:

我想这样称呼:

问题是类型参数TCommandBase,所以转换将是 to ICommandHandler<CommandBase>,例如,它不是由 实现的TestHandler。而且无论我是否可以正确转换它,我都无法返回ICommandHandler<TestCommand>when 的实现T=CommandBase

有没有办法解决这个问题?我没有特别锁定 GetHandler 方法,任何适合该HandleCommand方法的东西都很好(我需要有一个接受基类的单一入口点,并且我不能做一些 switch/case 整体)

0 投票
2 回答
233 浏览

f# - 函数类型的差异。接口

我试图了解函数类型的方差规则。似乎他们不会将输入和输出视为相同(直到对偶)。考虑这个程序。

这是错误:

我的理解seq<int>是一种接口类型,一种int list实现,所以我期待这个转换通过(*)。

两个问题:

  1. 为什么不呢?
  2. 为什么演员阵容mk2正常?

(*) 对于理论家:我期待阐述者在函数空间类型构造函数的输入和输出位置表现出双重行为。那是错的吗?

0 投票
1 回答
77 浏览

c# - 为什么我必须强制转换为类型参数并且不能使用约束类型?

谁能解释为什么我必须转换为 T 以及为什么 Add2 不接受 Bar 作为参数?

0 投票
2 回答
213 浏览

scala - 为什么下限类型会改变方差位置?

Scala 语言规范(关于方差注释的第 4.5 节,第 44 页)

  • 类型参数的变化位置与封闭类型参数子句的变化位置相反。
  • 类型声明或类型参数的下限的方差位置与类型声明或参数的方差位置相反。

使用上面的第一点,很容易(至少在形式上)看到

产生错误信息

并且使用第一点和第二点很容易看出

产生错误信息

正如我所提到的,很容易从形式上看出(即遵循方差注释的规则)为什么会发生这些错误。但是,我想不出一个例子来说明这些限制的必要性。相比之下,很容易想出一些例子来说明为什么方法参数应该改变方差位置,参见例如Checking Variance Annotations

所以,我的问题是:假设上面的两段代码是允许的,那么出现问题的例子是什么?这意味着,我正在寻找与此类似的示例,以说明在未使用上述两个规则的情况下可能出现的问题。我对涉及下限类型的示例特别感兴趣。

请注意,Scala type bounds & variance的答案让这个特定的问题悬而未决,而“下界”中给出的答案将反转类型的方差,但为什么呢?对我来说似乎错了。

编辑:我认为第一种情况可以按如下方式处理(改编上面引用的示例)。假设,以下是允许的

然后我们可以实现

并将其用作

这显然很麻烦。但是,我看不出如何调整它以表明“逆变类型参数+下类型界限”的组合也有问题?

0 投票
0 回答
63 浏览

c# - C#中对方差转换的某些限制的原因

关于协变和逆变的方法委托之间的隐式转换在 C# 中实现的方式,我有几个问题。

据我了解,方差处理对于将函数分配给不同的委托是隐含的,即:

(从概念上讲,虽然可能不是语义上的,但我相信这是逆变。当然,如果我的任何假设完全错误,我将不胜感激。)经过数小时的仔细研究,我相信我完全理解它是如何工作的以及为什么. 但我也了解到,我无法将方法从一种类型(委托)转换为另一种,即使它为相同的类型分配了相同的值,只需两个步骤:

问题1:为什么不呢?并且请不要说“因为你不使用'in'”或“因为它不是泛型类型”。我想知道这种行为的理由是什么,就像在某些情况下为了防止传递无效类型而设置了方差限制一样。现在,我还了解到 C# 支持使用关键字“in”和“out”进行显式委托转换。像这样:

但是没有泛型我不能做同样的事情:

我有一种感觉,其原因可能与不支持隐式方差转换的原因密切相关。

问题2:但是为什么?为什么我不能像这样使用'in'关键字:

再一次,我知道这不是它的工作原理,但是排除此功能的理论上的“我们不能因为如果有人做了这个”的原因是什么?

PS 这段代码已经编译以确保它的行为与我描述的一样,并且只需要一个包装类和两个空Dog : Animal类。

0 投票
3 回答
183 浏览

scala - 泛型类型,以便一个方法的结果可以再次用作另一个方法的参数

我的代码归结为工厂初始化一个对象,然后再次使用该对象执行其他操作:

据我了解,initialize无论.finishFactoryT

工厂本身在不知道是什么的地方被调用T

虽然变体 (2) 有效,但变体 (1) 不:

但我不知道如何解决这个问题。甚至可能吗?

编译器通过调用wrapper它自己无法判断的方法得到什么?从我的角度来看,obj的类型应该是_$6,因为编译器似乎将捕获的_. 我怎样才能让编译器意识到这一点,而不必为它引入一个全新的方法?

0 投票
2 回答
2388 浏览

c# - 为什么 C# 不支持变体泛型类?

以这个小的 LINQPad 为例:

它无法编译并出现此错误:

无效的方差修饰符。只有接口和委托类型参数可以指定为变体。

我看不出代码有任何逻辑问题。一切都可以静态验证。为什么不允许这样做?它会导致语言上的一些不一致,还是由于 CLR 的限制而被认为实施起来过于昂贵?如果是后者,作为开发人员,我应该对上述限制了解多少?

考虑到接口支持它,我本来希望类支持从逻辑上遵循。