在这种情况下,我有一个派生程度较高的类型的列表和另一个派生程度较低的类型的列表。为了避免派生较少的列表中出现任意困惑,我编写了一个 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 类型,因此测试结果为阳性首先不应该进行转换。有没有办法避免这个问题?
最佳答案
Is there a way to circumvent this issue?
是的 - 你施放它:
foreach (A a in listA)
{
if (a.GetType().ToString() == "Test.B")
{
listA.Remove(a);
listB.Add((B) a);
}
}
这会编译,但仍然会失败,因为您正在修改正在迭代的集合。解决此问题的最简单方法是迭代列表的副本:
foreach (A a in listA.ToList())
根据您的要求,还有各种其他替代方案。
请注意,使用 is
或 as
比比较类型名称更清晰。我还强烈建议您养成在所有 foreach
语句中使用大括号的习惯,即使是在正文中只有一条语句的语句,并遵循局部变量的常见命名约定 (例如,listA
而不是 ListA
)。
另请注意,这不是编译器“不够智能”的问题 - 这是编译器遵循 C# 语言规范规则的问题。 a
的编译时类型是 A
- 就这么简单。循环中碰巧出现的任何其他代码都不会更改该编译时类型,因此不会更改您使用它的方式。
虽然有时这可能很烦人,但它使语言变得更加简单且更可预测。如果以前的操作改变了重载解析的工作方式等,那将会真的很奇怪。
关于c# - 将隐含为派生程度较低的类型的对象放入派生程度较高的类型的列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27265914/