将隐含为派生类型较少的对象放入派生类型较多的列表中

本文关键字:类型 派生 列表 对象 | 更新日期: 2023-09-27 18:32:51

在这种情况下,我有一个派生类型较多的列表和另一个派生较少类型的列表。为了避免派生较少的列表出现任意混乱,我编写了一个 foreach 语句,用于检查列表中的每个元素是否属于派生较多的类型,如果是,则将其移动到派生较多的元素列表中。此处演示了这一点:

namespace Test
{
    class Tester
    {
        static void Method()
        {
            List<A> ListA = new List<A>();
            List<B> ListB = new List<B>();
            //populate the lists
            foreach (A a in ListA)
                if (a.GetType().ToString()=="Test.B")
                {
                    ListA.Remove(a);
                    ListB.Add(a);
                }
            //Do stuff with the lists
        }
    }
    class A
    {
        //stuff in class A
    }
    class B : A
    {
        //stuff in class B
    }
}

这给了我一个编译器错误,说 A 类型的对象不能隐式转换为类型 B,因为编译器不够聪明,无法意识到将被转换的 a 实例测试为类型 B 阳性,因此首先不应该进行转换。有没有办法规避这个问题?

将隐含为派生类型较少的对象放入派生类型较多的列表中

有没有办法规避这个问题?

是的 - 你投了它:

foreach (A a in listA)
{
    if (a.GetType().ToString() == "Test.B")
    {
        listA.Remove(a);
        listB.Add((B) a);
    }
}

这将编译,但它仍然会失败,因为您正在修改要迭代的集合。解决此问题的最简单方法是遍历列表的副本

foreach (A a in listA.ToList())

根据您的要求,还有其他各种选择。

请注意,使用 isas 比比较类型名称更干净。我还强烈建议您养成对所有foreach语句使用大括号的习惯,即使是正文中只有一个语句的语句,并遵循局部变量的常见命名约定(例如listA而不是ListA(。

另请注意,这不是编译器"不够聪明"的问题 - 而是编译器遵循 C# 语言规范规则的问题。a的编译时类型是A - 就这么简单。碰巧在循环中的任何其他代码都不会更改该编译时类型,因此不会更改使用它的方式。

虽然偶尔这可能很烦人,但它使语言变得更加简单和可预测。如果以前的操作改变了过载解决的工作方式等,那将非常奇怪。