最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

casting - C# compiler warnings about implicit casts in foreach loop (IDE0220) - Stack Overflow

programmeradmin3浏览0评论

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
  • You ask wrong questions. The issue is not even that something can fail during runtime, the issue is the misuse of the technology. And why do you show code that cannot even compile? Quite obviously, MyType does not implement ISomeType, unless you name the method ISomeType.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
  • 1 not "smart" enough – Ivan Petrov Commented Feb 14 at 7:21
  • @SergeyAKryukov I look forward to your comment/answer describing my misuse of the technology and how I can use it better. – beyarkay Commented Feb 14 at 8:19
  • “I look forward to your comment/answer describing my misuse.” I can think about it, but it is not easy, because I need to do a lot of guesswork on what you understand and what not. When your code sample does not even compile, it hardly makes sense. In brief: you need to access objects though interfaces, without casts. – Sergey A Kryukov Commented Feb 14 at 8:22
  • If you're willing to tell me that I'm wrong without being willing to show me how to be right, I have to assume your comment is in bad faith and that you care more about nit-picking examples than improving understanding. – beyarkay Commented Feb 14 at 8:33
Add a comment  | 

2 Answers 2

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.

发布评论

评论列表(0)

  1. 暂无评论