首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >带有泛型的C#子类:我需要为ctor提供一个额外的泛型参数,但是如何实现呢?

带有泛型的C#子类:我需要为ctor提供一个额外的泛型参数,但是如何实现呢?
EN

Stack Overflow用户
提问于 2020-10-04 12:16:37
回答 2查看 60关注 0票数 0

我有个课

代码语言:javascript
代码运行次数:0
运行
复制
public class LDBList<T> : List<T> where T : LDBRootClass {
    // typical constructor
    public LDBList(LDBList<T> x) : base(x) { }
    ...
}

但是我希望有一个额外的构造函数,它接受一个不同的泛型类型的列表(例如A),以及一个将A转换为T的函数,然后从它构建T列表,类似于

代码语言:javascript
代码运行次数:0
运行
复制
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泛型参数(它真的不喜欢构造函数)。但我把它放在哪里,事实上,这甚至是可能的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-04 12:26:00

我不相信您可以在这样的构造函数中添加额外的泛型类型。

我将重构转换器以完成LDBList实例的创建并返回实例,这样转换就像工厂一样从A的实例创建LDBLists。

代码语言:javascript
代码运行次数:0
运行
复制
public class Converter<T,A>
{
    public LDbList<T> CreateLdbList(IList<A>) {
       var list = new LdbList<T>();
       // do the conversion here
       return list;
    }
}

然后,将用法更改为

代码语言:javascript
代码运行次数:0
运行
复制
var Converter<X,Y> = new Converter();
var result = Converter.Convert(originalData);
票数 1
EN

Stack Overflow用户

发布于 2020-10-04 12:25:47

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

代码语言:javascript
代码运行次数:0
运行
复制
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));
        }
    }
}

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

您可以像这样声明一个助手类:

代码语言:javascript
代码运行次数:0
运行
复制
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>类一样)的list类中,如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
public LDBList(IEnumerable<T> items) : base(items)
{
}

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

例如,考虑到:

代码语言:javascript
代码运行次数:0
运行
复制
public class LDBRootClass
{
}

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

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

代码语言:javascript
代码运行次数:0
运行
复制
var strings = new List<string> { "One", "Two", "Three", "Four", "Five" };
var result  = new LDBList<DerivedLDBRootClass>(strings.Select(item => new DerivedLDBRootClass(item)));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64194477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档