I want to check multiple controls state in one method, in C# this would be accomplished like so:
if (((CheckBox)sender).Checked == true)
{
// Do something...
}
else
{
// Do something else...
}
So how can I accomplish this in VB?
C#:
(CheckBox)sender
VB:
CType(sender, CheckBox)
VB actually has 2 notions of casting.
CLR style casting
Lexical Casting
CLR style casting is what a C# user is more familiar with. This uses the CLR type system and conversions in order to perform the cast. VB has DirectCast and TryCast equivalent to the C# cast and as operator respectively.
Lexical casts in VB do extra work in addition to the CLR type system. They actually represent a superset of potential casts. Lexical casts are easily spotted by looking for the C prefix on the cast operator: CType, CInt, CString, etc ... These cast, if not directly known by the compiler, will go through the VB run time. The run time will do interpretation on top of the type system to allow casts like the following to work
Dim v1 = CType("1", Integer)
Dim v2 = CBool("1")
Adam Robinson is correct, also DirectCast is available to you.
DirectCast will perform the conversion at compile time but can only be used to cast reference types.
Ctype will perform the conversion at run time (slower than converting at compile time) but is obviously useful for convertng value types.
In your case "sender" is a reference type so DirectCast would be the way to go.
Casting in VB.net uses the keyword ctype.
So the C# statement (CheckBox)sender is equivalent to ctype(sender,CheckBox) in VB.net.
Therefore your code in VB.net is:
if ctype(sender,CheckBox).Checked =True Then
' Do something...
else
' Do something else...
End If
Related
I'm working on a program, and I need to be able to change a setting using a combobox. I'm getting
CS0266 Cannot implicitly convert type 'object' to 'FastColoredTextBoxNS.Language'. An explict conversion exists (are you missing a cast?)
Using the code:
{
fastColoredTextBox1.Language = comboBox1.SelectedItem
}
Does anyone know a simple way to fix this? If any more info is needed, I will gladly edit it in.
You must cast to the desired type, since the SelectedItem property returns the unspecific type Object.
fastColoredTextBox1.Language = DirectCast(comboBox1.SelectedItem, FastColoredTextBoxNS.Language)
Note there is also the CType function. In addition to performing type casts it also performs also type conversions. We do not need a conversion here, if the items in the ComboBox are of the required type. DirectCast just means, okay I know that the item with the runtime type Object is of the required type, just take it as such.
See also:
Casting DataTypes with DirectCast, CType, TryCast
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
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.
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.
How do I declare "as any" in VB.NET, or what is the equivalent?
The closest you can get is:
Dim var as Object
It's not exactly the same as VB6's as Any (which stores values in a Variant) but you can store variables of any type as Object, albeit boxed.
VB.NET does not support the as any keyword, VB.NET is a strongly typed language, you can however (with .NET 3.5) use implicit typing in VB
Dim fred = "Hello World" will implicitly type fred as a string variable. If you want to simply hold a value that you do not know the type of at design time then you can simply declare your variable as object (the mother of all objects) NOTE, this usually is a red flag for code reviewers, so make sure you have a good reason ready :-)
As Any must be referring to Windows API declarations, as it can't be used in variable declarations. You can use overloading: just repeat the declarations for each different data type you wish to pass. VB.NET picks out the one that matches the argument you pass in your call.
This is better than As Any was in VB6 because the compiler can still do type-checking.
I suppose you have problems with converting WinAPI declarations. Sometimes you can get away if you just declare your variable as string or integer because that is the real type of value returned.
You can also try marshaling:
<MarshalAsAttribute(UnmanagedType.AsAny)> ByRef buff As Object
VB.NET doesn't support the "As Any" keyword. You'll need to explicitly specify the type.