Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用AddRange添加子类的集合_C#_.net 3.5_Inheritance_Iteration - Fatal编程技术网

C# 使用AddRange添加子类的集合

C# 使用AddRange添加子类的集合,c#,.net-3.5,inheritance,iteration,C#,.net 3.5,Inheritance,Iteration,如果我有这两门课: class A {} class B : A {} 我创建了一个列表,但我想通过调用List.AddRange(List)向其中添加一个列表,但编译器拒绝: Argument '1': cannot convert from 'System.Collections.Generic.List<A>' to 'System.Collections.Generic.IEnumerable<B> 然而,这是相当没有表现力的,因为我想要的只是AddRange

如果我有这两门课:

class A {}
class B : A {}
我创建了一个列表,但我想通过调用List.AddRange(List)向其中添加一个列表,但编译器拒绝:

Argument '1': cannot convert from 'System.Collections.Generic.List<A>'
to 'System.Collections.Generic.IEnumerable<B>
然而,这是相当没有表现力的,因为我想要的只是AddRange

我可以用

List<B>.ConvertAll<A>(delegate(B item) {return (A)item;});
List.ConvertAll(委托(B项){return(A)项;});
但这是不必要的复杂和用词不当,因为我不是在转换,我是在铸造


问题:如果我要编写自己的类似列表的集合,我会向其中添加什么方法,使我能够将B的集合复制到a的集合中,作为类似于List.AddRange(List)的一行,并保持最大的类型安全性。(我所说的最大值是指参数既是一个集合又是一个类型内在性检查。)

这显然不起作用,因为.net中的泛型(还)不支持协方差

但是,您可以创建一个小型帮助器方法或类来解决此问题

如果实现自己的列表类,则可以使用其他常规参数添加协方差:

class MyList<T> {
    void AddRange<U>(IEnumerable<U> items) where U: T {
        foreach (U item in items) {
            Add(item);
        }
    }
}
类MyList{
void AddRange(IEnumerable items),其中U:T{
foreach(项目中的U项){
增加(项目);
}
}
}

不幸的是,这不起作用,因为.net中的泛型还不支持协方差

但是,您可以创建一个小型帮助器方法或类来解决此问题

如果实现自己的列表类,则可以使用其他常规参数添加协方差:

class MyList<T> {
    void AddRange<U>(IEnumerable<U> items) where U: T {
        foreach (U item in items) {
            Add(item);
        }
    }
}
类MyList{
void AddRange(IEnumerable items),其中U:T{
foreach(项目中的U项){
增加(项目);
}
}
}

我唯一能想到的就是这个

public class MyList<T> : List<T>
{
    public void AddRange<Tother>(IEnumerable<Tother> col)
        where Tother: T
    {    
        foreach (Tother item in col)
        {
            this.Add(item);
        }
    }
}
公共类MyList:列表
{
公共无效添加范围(IEnumerable列)
托特在哪里
{    
foreach(列中的其他项目)
{
本条增加(项目);
}
}
}

调用它意味着执行MyList.AddRange(MyList)。如果参数不可枚举,或者类型继承不起作用,因此无法满足我的问题的最大类型安全要求,则此操作将失败。

我唯一能想到的是

public class MyList<T> : List<T>
{
    public void AddRange<Tother>(IEnumerable<Tother> col)
        where Tother: T
    {    
        foreach (Tother item in col)
        {
            this.Add(item);
        }
    }
}
公共类MyList:列表
{
公共无效添加范围(IEnumerable列)
托特在哪里
{    
foreach(列中的其他项目)
{
本条增加(项目);
}
}
}

调用它意味着执行MyList.AddRange(MyList)。如果参数不可枚举,或者类型继承无法满足我的问题的最大类型安全要求,则此操作将失败。

您不能只执行以下操作:

listOfAItems.AddRange(listOfBItems.Cast<A>());
listOfAItems.AddRange(listOfAItems.Cast());
你就不能这样做:

listOfAItems.AddRange(listOfBItems.Cast<A>());
listOfAItems.AddRange(listOfAItems.Cast());

实际上,泛型类型现在并不是变体。在C#4.0中,IEnumerable
将可转换为IEnumerable
实际上,泛型类型现在并不是变体。在C#4.0中,IEnumerable
将转换为IEnumerable
我能够使用LINQ实现这一点

listOfAItems.AddRange(listOfBItems.Cast<A>());
listOfAItems.AddRange(listOfAItems.Cast());

我能够使用LINQ实现这一点

listOfAItems.AddRange(listOfBItems.Cast<A>());
listOfAItems.AddRange(listOfAItems.Cast());

如果您发现自己处于泛型类型不可变的情况下,以下扩展方法可以让您的生活更轻松:

public static void AddRange<TList,TOther>(this List<TList> list, IEnumerable<TOther> collection) where TOther: TList {
    foreach(TOther e in collection) {
        list.Add(e);
    }
}
publicstaticvoidaddrange(此列表,IEnumerable集合),其中TOther:TList{
foreach(托特收藏){
列表.添加(e);
}
}
不必从
List
派生,也不必在某些实用程序类中使用此方法,而是将其用作扩展方法,从而简化了使用。您还可以从推断中获益,因此此以前无效的调用将在不进行任何修改的情况下变为有效:

List<Animal> animals;
List<Dog> dogs;
animals.AddRange(dogs);
列出动物;
列出狗的名单;
动物。范围(狗);

如果您发现自己处于泛型类型不可变的情况下,以下扩展方法可以让您的生活更轻松:

public static void AddRange<TList,TOther>(this List<TList> list, IEnumerable<TOther> collection) where TOther: TList {
    foreach(TOther e in collection) {
        list.Add(e);
    }
}
publicstaticvoidaddrange(此列表,IEnumerable集合),其中TOther:TList{
foreach(托特收藏){
列表.添加(e);
}
}
不必从
List
派生,也不必在某些实用程序类中使用此方法,而是将其用作扩展方法,从而简化了使用。您还可以从推断中获益,因此此以前无效的调用将在不进行任何修改的情况下变为有效:

List<Animal> animals;
List<Dog> dogs;
animals.AddRange(dogs);
列出动物;
列出狗的名单;
动物。范围(狗);

Um,我没有List.Cast()方法。您是在引用System.Linq吗?如果您运行的是.NET 2.0,我很抱歉,as Cast是Linq扩展方法之一。True,因此它仅在.NET 3.5版(或更新版本,发布时)中可用。然而,虽然扩展方法在代码中是“干净”的,但它们并不总是非常有效。在这种情况下,如果经常调用,我相信使用泛型参数的方法要快得多。@Lucero:那不是真的。就性能而言,它们并不比任何其他方法慢。有时相反!嗯,我没有List.Cast()方法。你是在引用System.Linq吗?如果您运行的是.NET 2.0,我很抱歉,as Cast是Linq扩展方法之一。True,因此它仅在.NET 3.5版(或更新版本,发布时)中可用。然而,虽然扩展方法在代码中是“干净”的,但它们并不总是非常有效。在这种情况下,如果经常调用,我相信使用泛型参数的方法要快得多。@Lucero:那不是真的。就性能而言,它们并不比任何其他方法慢。有时相反!“如果参数不可枚举或类型继承不起作用,则此操作将失败。”-至少对我来说,这是预期的行为。你会怎么想,或者这是怎么一个问题?这正是我所怀疑的。我的意思是,这满足了我的问题中关于最大类型安全性的要求。此外(不确定是否在编辑中添加了它)的类型设置“