我们使用.NET Framework 3.5创建了一些类,如下所示:
public class A
{
public override string ID { get; set; }
public override string Name { get; set; }
private List<B> versionen = new List<B>();
public List<B> Versionen
{
get { return versionen; }
set { versionen = value; }
}
}
由其他类中的方法使用,如
private static void DoSomething(List<A> versioningObj)
{
foreach (A concretClassAObject in versioningObj)
{
foreach (B concretClassAVersionObject in concretClassAObject.Versionen)
{
}
}
}
要重构此代码并开发一个通用方法,我尝试实现以下接口:
public interface VersioningObject<T> : IIDIdentifiable where T : IIDIdentifiable
{
string Name { get; set; }
List<T> Versionen { get; set; }
}
public interface IIDIdentifiable
{
string ID { get; set; }
}
A类实现&#39; VersioningObject&#39; B类实现&#39; IIDDIdentifiable&#39;。新方法如下所示:
private static void DoSomething(List<VersioningObject<IIDIdentifiable>> versioningObj)
{
foreach (VersioningObject<IIDIdentifiable> concretClassAObject in versioningObj)
{
foreach(IIDIdentifiable concretClassAVersionObject in concretClassAObject.Versionen) {
}
}
}
我尝试将此方法称为“DoSomething&#39;像:
List<A> myList = new List<A>() {new A()};
DoSomething(myList);
并收到以下错误:
我怎么能解决这个问题。非常感谢你提前!
答案 0 :(得分:0)
List
和VersioningObject
在其通用参数方面都不具有协变性。因此,VersioningObject<Child>
无法隐式转换为VersioningObject<Parent>
(其中Child
扩展Parent
)。即使它是(当前它不能协变,因为它接受泛型参数作为输入),那么List<VersioningObject<Child>>
仍然不能隐式转换为List<VersioningObject<Parent>>
。
要完成所有这些,你需要制作几个相当基础的重构。
1)VersioningObject
只需要揭示如何读取值,而不是写入它们,从而使它成为概念上的协变:
public interface VersioningObject<out T> : IIDIdentifiable where T : IIDIdentifiable
{
string Name { get; }
List<T> Versionen { get; }
}
2)DoSomething
需要接受IEnumerable
,而不是List
。 IEnumerable
是协变的,因为它只允许使用泛型参数读取数据。 DoSomething
只需要在您显示的内容中迭代数据,所以这应该没问题。如果您需要实际使用List
特定成员,那么这根本不可能。
private static void DoSomething(
IEnumerable<VersioningObject<IIDIdentifiable>> versioningObj)
{
//...
}
此外,通用协方差仅在.NET 4.0中添加,因此您需要将该版本的框架用于任何选项。