I see misuse of these 2 operators on every and each forum approximately at least couple of times a week. People don’t know/realise (or don’t want to) that there is significant difference in two code snippets below (I found similar on one of the forums):
Both snippets will throw an exception. But, there is a big BUT.
The first snippet will throw NullReferenceException (Object reference not set to an instance of an object). Go and guess what’s going on. Especially in production when you probably don’t have call stack with code line information, especially in just a bit more complex scenario. No useful information here at all.
The second one will throw too, but it will be InvalidCastException (Unable to cast object of type 'System.Collections.Generic.List`1[System.String]' to type 'System.Collections.Generic.IList`1[System.Int32]').
See the difference? The later one tells you what exactly is wrong so you have a good starting point of fixing the issue.
Generally I would tell to never use AS operator (even if you think you know the exact type NOW, you cannot be sure tomorrow) unless:
Additionally, in any case you should check the casting result for null. Always check it for null. Do you hear me? ALWAYS!
var unknown = (object)new List<string>(); // Snippet 1: as operator foreach (var item in unknown as IList<int>) { // Do something with item } // Snippet 2: cast operator foreach (var item in (IList<int>)unknown) { // Do something with item }
Both snippets will throw an exception. But, there is a big BUT.
The first snippet will throw NullReferenceException (Object reference not set to an instance of an object). Go and guess what’s going on. Especially in production when you probably don’t have call stack with code line information, especially in just a bit more complex scenario. No useful information here at all.
The second one will throw too, but it will be InvalidCastException (Unable to cast object of type 'System.Collections.Generic.List`1[System.String]' to type 'System.Collections.Generic.IList`1[System.Int32]').
See the difference? The later one tells you what exactly is wrong so you have a good starting point of fixing the issue.
Generally I would tell to never use AS operator (even if you think you know the exact type NOW, you cannot be sure tomorrow) unless:
- You explicitly expect different type(s).
- You want to determine type using IS operator (really bad practice, consider simple polymorphism instead).
- You want to improve performance (though it is really, really rarely worth it).
Additionally, in any case you should check the casting result for null. Always check it for null. Do you hear me? ALWAYS!