繁体   English   中英

带有泛型的 C# 子类化:我需要一个额外的 ctor 泛型参数,但是如何?

[英]C# subclassing with generics: I need an extra generic parameter for ctor, but how?

我有一堂课

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));
    }
}

所以converterA->T类型,所以我取一个A列表并从中制作一个T列表。 我的班级由T参数化,所以很好。

但它抱怨“找不到类型或命名空间名称'A'”。

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

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

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)));

我不相信您可以向这样的构造函数添加其他泛型类型。

我会重构转换器以进行创建并返回 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);

暂无
暂无

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

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