繁体   English   中英

为什么我不能将类型约束的泛型参数转换为约束类型?

[英]Why can't I cast a generic parameter with type constraint to the constrained type?

我习惯于使用接口,泛型并在真实环境中使用继承来开发它们,同时尝试使用并将其实现为我们即将开展的项目之一的新架构,并且我对于我对此感到困惑的泛型有疑问。

这对我自己来说更像是一个教育问题,因为我无法理解为什么.NET不允许这样做。

如果我有一个泛型类(Of T As IA, T2 As A)那么我有以下接口和实现基接口的类

Public Interface IA
  Property A As String
End Interface
Public Interface IB
  inherits IA
  Property B As String
End Interface

Public Class GenericClass(Of T As IA, T2 As A)
  'Should be list of IA?
  Public list As New List(Of T)
  Public Sub Add()
  End Sub
End Class

因为我已经把T as IA为什么在add方法中是Dim foo4 As T = New A()不合法的时候

Dim foo1 As IA = New A()
Dim foo2 As T
Dim foo3 = Activator.CreateInstance(Of T2)()
Dim x As IA = foo2
Dim y As IA = foo3
list.Add(x)
list.Add(y)

以上都是? 这对于我来说已经成为一个学习曲线,但是我对于为什么我在逻辑上无法做到这一点感到非常困惑?

编辑:抱歉忘记了Class A ,错误信息请参见下文

Public Class A
  Implements IA
  Public Property A As String Implements IA.A
End Class

编辑2:错误输入错误

“类型a的值不能转换为T”

目前还不清楚你要做什么,但我注意到的一个问题是你似乎假设List<TypeThatImplementsIA>在某种程度上可以与List<IA>互换。 事实并非如此。 想象一下A是一类飞鸟, IA是由可以飞行的生物实现的,有人创造了GenericClass<Airplane, BlueJay) 尽管AirplaneBlueJay都是可以飞行的东西,但是人们无法将BlueJay添加到List<Airplane> 框架中可以使用GenericType<DerivedType>作为GenericType<BaseType>的一种常见情况是使用IEnumerable<T> 原因是人们无法将T存储到IEnumerable<T>中 - 只能读出它们。 如果一个人期待一个IEnumerable<Animal>并且一个人得到一个IEnumerable<MaineCoonCat> ,那么每当一个人想要读一个Animal ,就会读取一个MainCoonCat实例,它继承自Animal ,因此可以替代它。 IEnumerable<T>这个特性称为协方差

但是,这种行为存在限制,这是因为使用接口作为一种存储位置(变量,参数等)与使用它作为约束之间存在差异。 对于每个非可空值类型,Runtime中实际上有两个相关类型。 其中一个是真正的值类型,它没有继承的概念(但可以实现接口)。 另一种是从ValueType派生的堆对象类型(后者又从Object派生)。 大多数.net语言将隐式地将前一种类型转换为后者,并允许代码将后者明确地转换为前者。 接口类型存储位置只能保存对堆对象的引用。 an instance of that interface type. 这是显著,因为这意味着,尽管它实现的接口的结构是转换为该接口类型,这并不意味着该结构的实例 ,接口类型的实例。 协方差的前提是,例如IEnumerable<DerivedType>返回的每个对象都可以直接用作BaseType的实例, 而无需转换 这种直接替代性适用于继承的类类型,以及由类类型实现接口。 它不适用于结构类型实现的接口,也不适用于没有class约束的泛型。 将类约束添加到泛型类类型参数将允许该类型参数参与协方差,但可能排除使用结构作为泛型类型参数。 请注意,除非有特殊理由期望接口将由结构实现(例如IComparable<T> ,在许多情况下,接口不太可能由结构实现,因此class约束将是无害)。

那是因为T不是接口IA本身。 这是它的一个实现。

假设您有另一个实现IA类:

Public Class B
  Implements IA
  Public Property B_A As String Implements IA.A
  Public Property OtherProperty as Object
End Class

然后你创建一个新的Generic Class实例,如下所示:

Dim genericObject as new GenericClass(Of B, A)

所以在这种情况下, T现在是BA不能转换为B

在这种情况下,替换你的疑问部分,一个对我有意义的代码:

Dim foo4 As IA = New T()

编辑由于评论

为了能够实例化T ,有必要在类型定义中声明New约束。 所以泛型类声明将是:

Public Class GenericClass(Of T As {New, IA}, T2 As A)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM