簡體   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