用泛型进行C#子类化:我需要一个额外的ctor泛型参数,但怎么做呢



我有一个类

public class LDBList<T> : List<T> where T : LDBRootClass {
// typical constructor
public LDBList(LDBList<T> x) : base(x) { }
...
}

但我想要一个额外的构造函数,它接受一个不同泛型类型的列表(比如a(,以及一个将a转换为T的函数,并以此构建T列表,类似

public LDBList(
Func<A, T> converter, 
IList<A> aList)
{
foreach (var x in aList) {
this.Append(converter(x));
}
}

所以converter是类型A->T,所以我取一个A列表,并从中生成一个T列表。我的类由T参数化,所以这没关系。

但它在抱怨"未能找到类型或命名空间名称"A";。

好吧,所以我想它需要类上的A泛型参数(它真的不喜欢构造函数上的参数(。但我该把它放在哪里呢?事实上,这可能吗?

我不相信你能向这样的构造函数添加额外的泛型类型。

我会重构转换器来创建并返回LDBList的实例,这样转换就充当了从a.的实例创建LDBLists的工厂

public class Converter<T,A>
{
public LDbList<T> CreateLdbList(IList<A>) {
var list = new LdbList<T>();
// do the conversion here
return list;
}
}

然后,将用法更改为

var Converter<X,Y> = new Converter();
var result = Converter.Convert(originalData);

理论上,您可以将额外的类型添加到类本身的泛型类型中:

public class LDBList<A, T> : List<T> where T : LDBRootClass
{
// typical constructor
public LDBList(LDBList<A, T> x) : base(x) { }
public LDBList(
Func<A, T> converter,
IList<A>   aList)
{
foreach (var x in aList)
{
this.Append(converter(x));
}
}
}

当然,这意味着您需要用一个额外的类型参数来声明该类型的实例,除非您使用特定的构造函数,否则您甚至不需要这个参数。所以这不好。

可以声明一个助手类,如下所示:

public static class LDBListCreator
{
public static LDBList<T> CreateFrom<T, A>(Func<A, T> converter, IList<A> aList) where T: LDBRootClass
{
var result = new LDBList<T>();
result.AddRange(aList.Select(converter));
return result;
}
}

这假设LDBList<T>有一个默认的构造函数。

但经过检查,您应该能够看到创建这样一个简单的辅助类是毫无意义的。如果您在列表类中添加一个接受IEnumerable<T>的构造函数(就像List<T>类一样(,如下所示:

public LDBList(IEnumerable<T> items) : base(items)
{
}

然后,只需使用IEnumerable.Select()就可以构造LDBList<T>的实例。

例如,给定:

public class LDBRootClass
{
}
public class DerivedLDBRootClass : LDBRootClass
{
public DerivedLDBRootClass(string value)
{
// .. whatever
}
}

然后,您可以非常简单地从List<string>转换为LDBList<DerivedLDBRootClass>,而无需任何额外的脚手架,如下所示:

var strings = new List<string> { "One", "Two", "Three", "Four", "Five" };
var result  = new LDBList<DerivedLDBRootClass>(strings.Select(item => new DerivedLDBRootClass(item)));

最新更新