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

时间:2014-12-03 07:24:57

标签: c# inheritance

在这种情况下,我有一个更多派生类型的列表和另一个派生类型较少的列表。为了避免派生较少的列表中的任意混乱,我写了一个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类,因为编译器不够聪明,无法实现转换的实例被测试为类型为正B所以首先不应该进行转换。有没有办法绕过这个问题?

1 个答案:

答案 0 :(得分:5)

  

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

是的 - 你投了它:

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语句使用大括号的习惯,即使在语句中只有一个语句的大括号,并遵循局部变量的通用命名约定({{1}例如,而不是listA

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

虽然偶尔这可能很烦人,但它使语言更加简单和可预测。如果先前的操作改变了重载决策的工作方式等,那么真的很奇怪。