As a simplified example of my problem, I've got an array of ISomeType
, and I want to loop over all the elements in that array that are actually MyType
, but I'm getting IDE0220 warnings "Add explicit cast in foreach loop" that I don't think apply. Here's a code example:
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
}
The compiler complains that it implicitly casts the elements of maybeFooBars
into MyType
, and that this can fail at runtime, so I should be explicit about the cast:
// 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>())
Could my code actually fail at runtime, since I'm checking the type and only implicitly casting if the type is correct? Or is the C# compiler not smart enough to see that I've guarded against the types being incorrect?
As a simplified example of my problem, I've got an array of ISomeType
, and I want to loop over all the elements in that array that are actually MyType
, but I'm getting IDE0220 warnings "Add explicit cast in foreach loop" that I don't think apply. Here's a code example:
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
}
The compiler complains that it implicitly casts the elements of maybeFooBars
into MyType
, and that this can fail at runtime, so I should be explicit about the cast:
// 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>())
Could my code actually fail at runtime, since I'm checking the type and only implicitly casting if the type is correct? Or is the C# compiler not smart enough to see that I've guarded against the types being incorrect?
Share Improve this question asked Feb 14 at 6:17 beyarkaybeyarkay 1,0451 gold badge8 silver badges27 bronze badges 5 |2 Answers
Reset to default 4.Where(i => i.GetType() == typeof(MyType))
won't tell the compiler that you're dealing with only MyType
members. For that you'll want OfType
instead. So you'll be using it like
foreach (MyType foobar in maybeMyTypes.OfType<MyType>()) {
// use the MyType methods availbale on foobar
}
GetType
is a runtime-operation, it won't help the compiler to infer the right type. So for the compiler, your Where
-statement just returns a list of ISomeType
. So you get the waring, that you need to convert the type to the derived one.
Furthermore, your Where
-statement will just select the items matching the condition. It won't transform your items to the desired type. Where
just returns the exact same type of collection it got as parameter. So if the input-collection to Where
is of type ISomeType
, this applies to the output as well.
So afterall what you want instead is select these objects whose type is of the desired one and cast them appripriately. So use OfType
instead, which is similar to performing an as
-cast and returning those whose return-value isn't null
. Alternativly you can use Cast<MyObject>
, however that will give you an InvalidCastException
if there's any element that isn't of that type.
MyType
does not implementISomeType
, unless you name the methodISomeType.DoThing
or make it public. Perhaps you need to read on the fundamentals of OOP, interfaces, and so on. – Sergey A Kryukov Commented Feb 14 at 6:27