Why use TryCast instead of DirectCast? - vb.net

When I am trying to cast Object obj to Type T, if it can not be cast then there is something wrong.
And after I cast the object I will be looking for working with the cast object.
Rather I will be expecting to get an exception at the place where I will be casting it than say where I will be using that object.
In this sense, is it better to use DirectCast instead of TryCast?
Or am I missing some other significance of using TryCast?

(For C# developers, TryCast is similar to "as" and DirectCast is the equivalent of normal casting. As Mike pointed out in the comments, "as" works for nullable value types, but TryCast doesn't.)
If the value really should be a T, then DirectCast is indeed the right way to go - it fails fast, with an appropriate error.
TryCast is appropriate when it's legitimate for the target to be the "wrong" type. For instance, to get all the Button controls in a container, you could go through the control collection and try to cast each to Button. If it works, you do something with it - if it doesn't, you move on. (With LINQ you can just use OfType for this purpose, but you see what I mean...)
In my experience direct casting is appropriate more often than TryCast - although with generics I find myself casting a lot less often than I used to anyway.

The only difference between the two is that, a TryCast will return a null if it fails, while a DirectCast will throw an exception.
These has implications on how you can handle your program. Personally I prefer not having to throw an exception if the possibility of an improper cast (e.g., text input boxes for user input being cast into numeric types) is pretty high.

I think the others have mentioned the times when you should and shouldn't perform "safe casting" (where you ensure that the cast can succeed before risking an exception). If your program does need to perform safe casting then the TryCast method saves both you and the program some work.
I wasn't aware of the TryCast() function until today, and I feel like a fool for using the 'bad' method of safely casting.
If you did not know about the TryCast() function then you might end up with something like this:
'' wasteful, the TypeOf and DirectCast calls are redundant
If TypeOf obj Is SomeClass Then
someObj = DirectCast(obj, SomeClass)
'' More code
End If
The problem is that this method actually performs two casts (technically I think they're actually type-checks). Using the TryCast and checking if the result is Nothing eliminates the 2nd cast and saves needless work.
'' efficient, only one cast is ever performed and there are no InvalidCastExceptions thrown
someObj = TryCast(obj, SomeClass)
If someObj IsNot Nothing Then
'' More code
End If
Following this pattern lets you avoid having to handle expensive exceptions, and efficiently cast to the correct type.

If your design mandates that the object passed to you MUST be of type T, then assert (as in Debug.Assert) that the cast succeeds in debug builds and run exhaustive unit tests to prove that your implementation follows your design.
With your design proven and tested, you can perfrom the direct cast knowing that it can never fail.

Related

Implicit Interface casts of Nullables

With VB's Option Strict On, why does a Nullable(Of T) not require an explicit cast to an interface of T when it does require one to T?
I.e.
Dim x As Integer? = 5
Dim y As Integer
Dim z As IComparable
y = x ' Fails to compile with error
' "Option Strict On disallows implicit conversions from 'Integer?' to 'Integer'."
z = x ' Succeeds
EDIT: As (sort of) shown by #SSS, part of the answer is that Nullable values are, well, nullable, and can be Nothing, which is fine for a reference like an interface. So this conversion will always succeed, unlike the conversion to T case (which fails when the Nullable has no value), and so it can be seen as an implicit conversion.
My question now becomes "how?". How is the conversion from a Nullable(Of T) (which has no interfaces of its own) to an interface of T theoretically negotiated?
I know the implementation is box Nullable<T>, which effectively strips the Nullable wrapper, but I'm confirming the concept here...
(So I'll review the documentation and see if they explain this.)
I don't see the problem?
y = x
can fail because x could hold a value of Nothing, but y is not allowed to hold a value of Nothing. The IComparable interface allows Integers to be compared to Nothing however, so that assignment is fine.
Notice that if you swap it round:
x = y
then this succeeds because every value of y can be assigned to x.
You can confirm that Integers can be compared to Nothing as follows:
MsgBox(5.CompareTo(Nothing))
From what I can tell in vb.net, the statement interfaceVariable = nullableVariable is essentially equivalent to interfaceVariable = if(nullableVariable.HasValue, CType(nullableVariable.Value, interfaceType), Nothing). The C# compiler seems to handle things the same way: interfaceVariable = nullableVariable; becomes interfaceVariable = nullableVariable.HasValue ? (interfaceType)nullableVariable.Value : null;.
If the type of nullableValue.Value implements the interface, then nullableVariable.Value will either perform return a value-type result or throw an exception. Since there exists a guaranteed boxing conversion from the return value to the interface, the cast will be legal. The only way the above code could fail would be if the nullable variable gets written between the calls to HasValue and Value, such HasValue sees the variable as non-null, but Value sees it as null and throws an exception. I believe that writing interfaceVariable = nullableVariable just tests nullity once, so that an exception could not occur; instead, an indeterminate value would get boxed.
Without actually reading documentation yet, I'm going to attempt an answer:
Firstly, the higher-level answer is that casting a Nullable to an interface is "safe" and will not throw, so it is logically a Widening operator and should not need to be explicit (compared to casting to T, when .HasValue is False it throws, so it should not be implicit with Option Strict On).
However, technically the "how" is a bit obscure: Even though some of the behaviour of Nullable is encoded in the metadata available via reflection, much of its "magic" is hidden in:
the runtime behaviour of box on a Nullable (and thus the compiler knows when to leave "lifting" to that), and
the other points made by Eric Lippert in his answer for C# and their equivalent in VB.NET.
It looks like S. Somasegar's blog post announcing changes to Nullable support in a late beta release for VS2k5 is also relevant here.

Is it good practice to define "what my variable will be"?

So I have this:
Dim aBoolean As Boolean = True
Will it make any difference to just do this?
Dim aBoolean = True
In other languages, I believe it was a good practice to also define the type of variable it would be, for performance or something. I am not entirely sure with VB.NET.
Thanks.
It depends. Explicitly defining the variable can improve readability, but I don't think it's always necessary. (To be clear, it has nothing to do with the actual functionality of your code).
In this specific example, you follow the declaration with a Boolean assignment of True, so it's already crystal clear that aBoolean is actually a Boolean when it is declared. The As Boolean syntax is not as necessary in this scenario.
Other cases may not be so clear. If the declaration was followed by the result of a function call, for example, it might be more clear to explicitly declare that the variable is a Boolean. e.g.
Dim aBoolean As Boolean = TestValidityOfObject(o)
As long as you have Option Infer turned on, it won't make a bit of difference. The second line is just a syntactic abbreviation for the first. At that point, it's up to your style preference as to which you should use.
Before type inference, there were performance issues when not declaring the type, but that's no longer an issue; due to type inference the variable will be of type Boolean whether you declare it or not.
Declaring the type can help the compiler catch errors sooner, and will often give you better Intellisense.
You're using what's called "type inference". This is where the compiler figures out at compile time what the type on the right side of the assignment is and uses that as the type of the variable.
This is, in general, a safe and convenient feature. However, there are a couple of things to keep in mind:
You must have Option Infer on; otherwise, the compiler doesn't do type inference and, depending on your setting for Option Strict, instead either gives you a compile time error (Option Strict On) or types your variable as Object and uses late binding everywhere. This is Pure Evil. (Option Strict Off)
In your particular case, there's no way for the compiler to mess up. HOWEVER, it's possible to use type inference in such a way as to change the semantics of your code:
For instance...
Dim myClass as MyBaseClass = New SubClass()
This is perfectly legal; we're typing the variable as a base class and assigning a value to it that represents an instance of a subclass. Nothing special. However, if we switch to type inference by just removing the type declaration...
Dim myClass = New SubClass()
Type inference will now see myClass as a SubClass instead of MyBaseClass. This might seem obvious, but the point is that you should be aware of what it's doing.
For more information and long-winded discussion about using type inference, see this question. While that question is targeted at C#, the only real difference is the first item that I listed above. Everything else is conceptually the same.

Difference between DirectCast() and CType() in VB.NET

I am an experienced C/C++/C# programmer who has just gotten into VB.NET. I generally use CType (and CInt, CBool, CStr) for casts because it is fewer characters and was the first way of casting which I was exposed to, but I am aware of DirectCast and TryCast as well.
Simply, are there any differences (effect of cast, performance, etc.) between DirectCast and CType? I understand the idea of TryCast.
The first thing to note is VB.NET does not have a direct analog to C#'s (type)instance casting mechanism. I bring this up because it's useful as a starting point and common reference in comparing the two VB.NET operators (and they are operators, not functions, even though they have function semantics).
DirectCast() is more strict than the C# casting operator. It only allows you to cast when the item being cast already is the type you are casting to. I believe it will still unbox value types, but otherwise it won't do any conversion. So, for example, you can't cast from short to int, like you could with a C# (int) cast. But you can cast from an IEnumerable to an array, if your underlying IEnumerable object variable really is an Array. And of course you can cast from Object to anything, assuming the type of your object instance really is somewhere below your cast type in the inheritance tree.
This is desirable because it's much faster. There's less conversion and type checking that needs to take place.
CType() is less strict than the C# casting operator. It will do things you just can't do with a simple (int)-style cast, like convert a string to an integer. It has as much power as calling Convert.To___() in C#, where the ___ is the target type of your cast.
This is desirable because it's very powerful. However, this power comes at the cost of performance; it's not as fast as DirectCast() or C#'s cast operator because it might need to do quite a lot of work to finish the cast. Generally you should prefer DirectCast() when you can.
Finally, you missed one casting operator: TryCast(), which is a direct analog to C#'s as operator.
With CType you can write something like Ctype("string",Integer). But with DirectCast the above statement would give a compile time error.
Dim a As Integer = DirectCast("1", Integer) 'Gives compiler error
Dim b As Integer = CType("1", Integer) 'Will compile
DirectCast is more restrictive than CType.
For example, this will throw an error:
Sub Main()
Dim newint As Integer = DirectCast(3345.34, Integer)
Console.WriteLine(newint)
Console.ReadLine()
End Sub
It will also be shown in the Visual Studio IDE.
This however, does not throw an error:
Sub Main()
Dim newint As Integer = CType(3345.34, Integer)
Console.WriteLine(newint)
Console.ReadLine()
End Sub

VB CStr, CDate, CBool, etc. vs. DirectCast for casting without conversion

I usually avoid VB's built-in conversion functions (CStr, CDate, CBool, CInt, etc.) unless I need to do an actual conversion. If I'm just casting, say from an object to a string, I normally use either DirectCast or TryCast, under the assumption that CStr, etc., are doing some extra stuff I don't need. But sometimes the DirectCast syntax is a little cumbersome, as in the following example.
Dim value1 As String
Dim value2 As String
Using cn As New SqlConnection(cnStr)
Using cmd as New SqlCommmand(sqlStr, cn)
Using reader = cmd.ExecuteReader()
While reader.Read()
value1 = DirectCast(reader("COLUMN1"), String)
value2 = CStr(reader("COLUMN1"))
End While
End Using
End Using
End Using
SqlDataReader.Item returns an Object, which needs to be cast to a String. CStr is easier to read, type, and explain (IMO).
My question is, does it matter which one I use? Should I just go with CStr (and CDate and CBool, etc.) and not worry about the extra work I assume those functions are doing?
Is there any other downside to using these functions?
This is a good post with discussion in the comments about DirectCast versus the CType casts and variations.
In short, if you want to be explicit about it and know what to expect, DirectCast is suggested. On the other hand, a comment by Paul Vick (VB Technical Lead) says it doesn't matter much and to just use the CType variations.
Some useful links gleaned from that post:
How should I cast in VB.NET?
DirectCast Revealed (post on Paul Vick's blog)
In your example, you could just use:
value1 = reader("COLUMN1").ToString()
It will return the contents of the column as a string.
I always tend to favour using ToString() on an object if I can. Sometimes an object's ToString() method will return things like the class name of the object, rather then a content, so .ToString() isn't always an option.
I don't see the need for any of the VB functions CStr, CInt, etc, since the .NET framework provides plenty of good alternatives. For example.
Dim value As Integer = Convert.ToInt32(reader("Number").ToString())
Is a good way of converting a string to an int. It's worth reading up on these conversion methods, since the old VB style functions are only there for backwards compatability.
Most of the time, I use CStr, CInt, CBool and CType because it's shorter and easier to read. There might be a slight performance cost but most of the time it doesn't matter. It's good to know the differences between CType, TryCast, DirectCast, and others though.

IsNothing versus Is Nothing

Does anyone here use VB.NET and have a strong preference for or against using IsNothing as opposed to Is Nothing (for example, If IsNothing(anObject) or If anObject Is Nothing...)? If so, why?
EDIT: If you think they're both equally acceptable, do you think it's best to pick one and stick with it, or is it OK to mix them?
If you take a look at the MSIL as it's being executed you'll see that it doesn't compile down to the exact same code. When you use IsNothing() it actually makes a call to that method as opposed to just evaluating the expression.
The reason I would tend to lean towards using "Is Nothing" is when I'm negating it becomes "IsNot Nothing' rather than "Not IsNothing(object)" which I personally feel looks more readable.
I find that Patrick Steele answered this question best on his blog: Avoiding IsNothing()
I did not copy any of his answer here, to ensure Patrick Steele get's credit for his post. But I do think if you're trying to decide whether to use Is Nothing or IsNothing you should read his post. I think you'll agree that Is Nothing is the best choice.
Edit - VoteCoffe's comment here
Partial article contents: After reviewing more code I found out another reason you should avoid this: It accepts value types! Obviously, since IsNothing() is a function that accepts an 'object', you can pass anything you want to it. If it's a value type, .NET will box it up into an object and pass it to IsNothing -- which will always return false on a boxed value! The VB.NET compiler will check the "Is Nothing" style syntax and won't compile if you attempt to do an "Is Nothing" on a value type. But the IsNothing() function compiles without complaints. -PSteele – VoteCoffee
You should absolutely avoid using IsNothing()
Here are 4 reasons from the article IsNothing() VS Is Nothing
Most importantly, IsNothing(object) has everything passed to it as an object, even value types! Since value types cannot be Nothing, it’s a completely wasted check.
Take the following example:
Dim i As Integer
If IsNothing(i) Then
' Do something
End If
This will compile and run fine, whereas this:
Dim i As Integer
If i Is Nothing Then
' Do something
End If
Will not compile, instead the compiler will raise the error:
'Is' operator does not accept operands of type 'Integer'.
Operands must be reference or nullable types.
IsNothing(object) is actually part of part of the Microsoft.VisualBasic.dll.
This is undesirable as you have an unneeded dependency on the VisualBasic library.
Its slow - 33.76% slower in fact (over 1000000000 iterations)!
Perhaps personal preference, but IsNothing() reads like a Yoda Condition. When you look at a variable you're checking its state, with it as the subject of your investigation.
i.e. does it do x? --- NOT Is xing a property of it?
So I think If a IsNot Nothing reads better than If Not IsNothing(a)
I agree with "Is Nothing". As stated above, it's easy to negate with "IsNot Nothing".
I find this easier to read...
If printDialog IsNot Nothing Then
'blah
End If
than this...
If Not obj Is Nothing Then
'blah
End If
VB is full of things like that trying to make it both "like English" and comfortable for people who are used to languages that use () and {} a lot.
And on the other side, as you already probably know, most of the time you can use () with function calls if you want to, but don't have to.
I prefer IsNothing()... but I use C and C#, so that's just what is comfortable. And I think it's more readable. But go with whatever feels more comfortable to you.
I'm leaning towards the "Is Nothing" alternative, primarily because it seems more OO.
Surely Visual Basic ain't got the Ain't keyword.
I initially used IsNothing but I've been moving towards using Is Nothing in newer projects, mainly for readability. The only time I stick with IsNothing is if I'm maintaining code where that's used throughout and I want to stay consistent.
Is Nothing requires an object that has been assigned to the value Nothing. IsNothing() can take any variable that has not been initialized, including of numeric type. This is useful for example when testing if an optional parameter has been passed.