具有类的重构方法实现IList<;T>;
本文关键字:lt gt IList 实现 重构 方法 | 更新日期: 2023-09-27 18:25:51
我们用.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实现"VersioningObject",类B实现"IIDDIdentifiable"。新方法如下:
private static void DoSomething(List<VersioningObject<IIDIdentifiable>> versioningObj)
{
foreach (VersioningObject<IIDIdentifiable> concretClassAObject in versioningObj)
{
foreach(IIDIdentifiable concretClassAVersionObject in concretClassAObject.Versionen) {
}
}
}
我试着把这种方法称为"DoSomething",比如:
List<A> myList = new List<A>() {new A()};
DoSomething(myList);
并得到以下错误:
- 无法将"System.Collection.Generic.List"转换为"System.Collection.Generic.List>"
- DoSomeThing(System.Collections.Generic.List>)的最佳重载方法匹配包含一些无效参数
我该如何解决这个问题。提前非常感谢!
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)
{
//...
}
此外,通用协方差仅在.NET4.0中添加,因此您需要使用该版本的框架才能将其作为选项。