While reading C# code I found a rather curious snippet:
if( whatever is IDisposable) { (whatever as IDisposable).Dispose(); }
I'd rather expect that being done either like this:
if( whatever is IDisposable) { //check ((IDisposable)whatever).Dispose(); //cast - won't fail }
or like this:
IDisposable whateverDisposable = whatever as IDisposable; if( whateverDisposable != null ) { whateverDisposable.Dispose(); }
I mean as
is like a cast, but returns null
on failure. In the second snippet it can't fail (since there's a is
check before).
What's the point in writing code like in the first snippet instead of like in the second or in the third?
In C or C++, there is no special method for comparing NULL values. We can use if statements to check whether a variable is null or not. Here we will see one program. We will try to open a file in read mode, that is not present in the system. So the function will return null value.
The way you typically represent a “missing” or “invalid” value in C# is to use the “null” value of the type. Every reference type has a “null” value; that is, the reference that does not actually refer to anything.
Use Pointer Value as Condition to Check if Pointer Is NULL in C++ Null pointers are evaluated as false when they are used in logical expressions. Thus, we can put a given pointer in the if statement condition to check if it's null.
If a reference points to null , it simply means that there is no value associated with it. Technically speaking, the memory location assigned to the reference contains the value 0 (all bits at zero), or any other value that denotes null in the given environment.
You are correct. The first snippet does not make sense.
From the alternatives, I would recommend the third one, since it is thread-safe in the sense that between the check and the method call, the object cannot be replaced by another one which does not implement the interface. Consider the following scenario with the second snippet:
if (whatever is IDisposable) { //check // <-- here, some other thread changes the value of whatever ((IDisposable)whatever).Dispose(); // could fail }
This can't happen with the third snippet.
Note: There are some subtle differences between a cast and as
with respect to user-defined conversions, but they do not apply in this case.
is
followed by as
is a pointless construct, as you suspect. Ultimately, if you're not sure what type something is or what interfaces it implements, there are two idioms -- one for reference types and one for value types.
When testing for reference types (or a boxed nullable), the last pattern you provide is correct -- as
followed by a null test. This will be the fastest approach as the runtime will only have to perform one type test.
When testing for boxed value types, the second pattern you provide is correct -- is
followed by a cast.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With