作为我的问题的一个简化示例,我有一个数组ISomeType
,我想循环遍历该数组中所有实际的元素MyType
,但我收到IDE0220 警告“在 foreach 循环中添加显式强制转换”,我认为这不适用。以下是代码示例:
public interface ISomeType {
void DoThing();
}
public class MyType: ISomeType {
void DoThing() { /* do something */ }
void DoMyTypeThing() { /* do something specific to MyType */ }
}
public class YourType: ISomeType {
void DoThing() { /* do something */ }
void DoMyTypeThing() { /* do something specific to MyType */ }
}
ISomeType[] maybeMyTypes = [new MyType()];
// I get the error on this line because I cast the element into `MyType`
foreach (MyType foobar in maybeMyTypes.Where(i => i.GetType() == typeof(MyType))) {
// use the MyType methods availbale on foobar
}
maybeFooBars
编译器抱怨它隐式地将的元素转换为MyType
,并且这可能在运行时失败,所以我应该明确说明转换:
// Code with violations. var list = new List<object>(); foreach (string item in list) { } // Fixed code. var list = new List<object>(); foreach (string item in list.Cast<string>())
我的代码在运行时真的会失败吗?因为我正在检查类型,并且只在类型正确时进行隐式转换?还是 C# 编译器不够聪明,无法看出我已经防范了类型不正确?
.Where(i => i.GetType() == typeof(MyType))
不会告诉编译器你只处理MyType
成员。为此,你需OfType
要这样做。因此,你将使用它GetType
是运行时操作,它不会帮助编译器推断正确的类型。因此对于编译器,您的Where
语句仅返回一个列表ISomeType
。因此您会收到警告,您需要将类型转换为派生类型。此外,您的
Where
- 语句只会选择符合条件的项目。它不会将您的项目转换为所需的类型。Where
只返回与它作为参数获得的集合完全相同的类型。因此,如果输入集合的Where
类型为ISomeType
,这也适用于输出。所以,您最终想要的是选择这些类型为所需类型的对象,并对其进行适当的强制转换。因此,请使用
OfType
,这类似于执行as
-cast 并返回那些返回值不是 的对象null
。或者,您可以使用,但是如果存在任何不属于该类型的元素,Cast<MyObject>
它将返回。InvalidCastException