【问题标题】:C# Covariance generic parameter assignment/casting (implicit conversion)C# Covariance 泛型参数赋值/强制转换(隐式转换)
【发布时间】:2016-02-25 08:55:48
【问题描述】:

我有一个界面:

interface IInterface<T1, out T2> {};

一个抽象类实现IInterface&lt;&gt;

abstract class AbsClass<T2> : IInterface<String, T2> {};

以及其他抽象类继承自AbsClass&lt;&gt;

abstract class AbsAbsClassString : AbsClass<String, String> {};
abstract class AbsAbsClassTimeSpan : AbsClass<String, TimeSpan> {};

最后,

class CClassString1 : AbsAbsClassString {};
class CClassString2 : AbsAbsClassString {};
class CClassTimeSpan1 : AbsAbsClassTimeSpan {};
class CClassTimeSpan2 : AbsAbsClassTimeSpan {};
// and so on...

在我的 C3 代码中,我声明了 List&lt;IInterface&lt;String, Object&gt;&gt;

IList<IInterface<String, Object>> list = new List<IInterface<String, Object>>();
list.Add(new CClassString1());
list.Add(new CClassString2());
list.Add(new CClassTimeSpan1());
list.Add(new CClassTimeSpan2());

在每个list.Add(*) 句子中,编译器都会告诉我:

'System.Collections.Generic.ICollection(IInterface(String,object)).Add(IInterface(String,object))' 的最佳重载方法匹配有一些无效参数

参数 1:无法将类型 CClassString1 隐式转换为 IInterface(String,object)。存在显式转换(您是否缺少演员表?)

如果我测试:

IInterface<String, Object> i;
CClassString1 cs1 = new CClassString1();

i = (Interface<String,Object>)cs1;

最后一句抛出一个异常,告诉它不可能进行强制转换。

【问题讨论】:

  • 请提供minimal reproducible example。您当前的代码无法编译。您使用一个类型参数定义AbsClass,但使用两个类型参数。也许它只是完全不同的课程?
  • 对不起。由于@Jakub 暴露和回答的问题,它无法编译。
  • 您声称所有四个list.Add(*) 行都会给您编译错误。 Jakub 的回答只解释了最后两个。您还声称这个 (Interface&lt;String,Object&gt;)cs1 — 在运行时编译并抛出异常。但是,正如you can see yourself,在修复代码中的一些问题后,它会毫无例外地编译和运行。

标签: c# generics


【解决方案1】:

泛型接口协变和逆变只适用于引用类型。 TimeSpan 是值类型,所以 IInterface&lt;string, TimeSpan&gt; 不能转换为 IInterface&lt;string, object&gt;

这是因为变体强制转换是引用转换 - 它们不会改变对象的表示,它们只会改变引用的编译时类型。

【讨论】:

  • 我已经测试过用IInterface&lt;String, ReferenceValue&lt;TOut&gt; 创建一个ReferenceValue&lt;T&gt;。它似乎正在工作......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多