19

How should I cast from an Object to an Integer in VB.NET?

When I do:

Dim intMyInteger as Integer = TryCast(MyObject, Integer)

it says:

TryCast operand must be reference type, but Integer is a value type.

4
  • Why not this: CInt(MyObject) Commented Jan 16, 2016 at 23:19
  • @Dave - Read my comments on Abacus' answer. Cint (or any other conversion call) has a different purpose than TryCast/DirectCast. It is sensible if you have an incoming numeric value type, e.g. Single or Double, and want to truncate it to an Integer. Applying it to an incoming Object means you have no clue what is coming in, and what conversion work will be attempted. IMHO, it is a risky style of programming. Do what Jonathan shows, extending it if necessary. E.g., if you want to Parse a String, then check if its type is String, then call TryParse. Be explicit. Commented Feb 6, 2018 at 4:14
  • @Dave ... hopefully there will eventually be Numeric support in .Net. E.g. have all the numeric value types support an INumeric (or whatever) interface. Given that, instead of an incoming MyObject As Object one could have an incoming MyNumber As INumeric. OK, now we know "enough" about what is coming in, to do CInt(MyNumber), and be confident that we know what work will be done. Commented Feb 6, 2018 at 4:19
  • Lest anyone think I am suggesting that conversion operators be avoided, I am specifically talking about applying them to Object. I consider that a "code smell". I am recommending not using conversion operators until you have identified some interface or base class - so that you have some clue what you are asking to be done, and what might go wrong. Know whether you are asking for string parsing, or numeric truncation, or merely "unboxing". Commented Feb 6, 2018 at 4:27

4 Answers 4

34

TryCast is the equivalent of C#'s as operator. It is a "safe cast" operator that doesn't throw an exception if the cast fails. Instead, it returns Nothing (null in C#). The problem is, you can't assign Nothing (null) (a reference type) to an Integer (a value type). There is no such thing as an Integer null/Nothing.

Instead, you can use TypeOf and Is:

If TypeOf MyObject Is Integer Then
    intMyInteger = DirectCast(MyObject, Integer)
Else
    intMyInteger = 0
End If

This tests to see if the runtime type of MyObject is Integer. See the MSDN documentation on the TypeOf operator for more details.

You could also write it like this:

Dim myInt As Integer = If(TypeOf myObj Is Integer, DirectCast(myObj,Integer), 0)

Furthermore, if an integer with a default value (like 0) is not suitable, you could consider a Nullable(Of Integer) type.

Sign up to request clarification or add additional context in comments.

12 Comments

Why would the type of MyObject be Integer when we already know it is Object?
We don't already know that. We only know that MyObject is an Object reference. It could still point to an object of any type. The If TypeOf x Is type expression tests the runtime type of the object.
Lowercase, they mean nothing. Iif is a function, that has been replaced by the If operator in VB 2008. A quick look at the MSDN docs goes a long way. (I'm answering your questions and don't even know Visual Basic.)
Except going from a String "1" to an integer 1 is not a cast. It is a conversion (the string is parsed). The OP is specifically asking about casting an Object reference that he's assuming is an integer to an integer value. I'd appreciate those rep points back, thank you.
@CJ7 - using IIf here would fail (cause an exception if myObj is not an Integer). IIf always evaluates BOTH the true and false expressions; and then it returns whichever one is appropriate. The point of If(..) is that it only evaluates one expression or the other. In this case, it does not do DirectCast unless we have verified that we have an Integer. There is no situation in which using IIf(..) is a benefit; all uses of it in modern VB should be replaced by If(..).
|
5

You can use this:

Dim intMyInteger as Integer

Integer.TryParse(MyObject, intMyInteger)

2 Comments

No, this is an answer to a different question than was asked by OP, which was answered successfully two years ago. First, observe that Integer.TryParse() does NOT accept an Object as its first parameter. It only works on String. This should be your first clue that OP's question about casting is not the same as parsing.
String inherits from Object, and this answer is valid. This is another answer to OP's question which was successfully answered 2 year ago. This option has a benefit, if the object contains an integer value in String format, the successful answer wouldn't work but this answer will. On the other hand, my answer will require boxing and unboxing, so that's the downside.
3

Use Directcast and catch InvalidCastException

1 Comment

+1: At first glance, I thought this was not a good alternative, because exceptions are so expensive in .Net. However, OP did state he was expecting an Integer inside the Object; if it is indeed always (or almost always) an Integer, then it makes perfect sense to do the DirectCast, and only catch the (rare) exception. Though personally I use Jonathan's style, having been trained by years of .Net usage to avoid exceptions as "too expensive". Even in situations where they aren't.
2

The equivalent for TryCast is CType. Both will do a type conversion if it is possible. By contrast, DirectCast will only convert the type if it is that type already.

To illustrate, you can use CType to convert a String, or Short, or Double, to an Integer. DirectCast will generally give you a syntax/compile error if you do that; but if you try to go around the error by using type Object (this is called "boxing" and "unboxing"), it will throw an exception at run-time.

    Dim OnePointTwo As Object = "1.2"
    Try
        Dim temp = CType(OnePointTwo, Integer)
        Console.WriteLine("CType converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    Catch ex As Exception
        Console.WriteLine("CType threw exception")
    End Try
    Try
        Dim temp = DirectCast(OnePointTwo, Integer)
        Console.WriteLine("DirectCast converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    Catch ex As Exception
        Console.WriteLine("DirectCast threw exception")
    End Try

This will output:

    CType converted to: 1 (type: System.Int32)
    DirectCast threw exception

So to most closely follow the TryCast semantics, I suggest using a function like this:

Shared Function TryCastInteger(value As Object) As Integer?
    Try
        If IsNumeric(value) Then
            Return CType(value, Integer)
        Else
            Return Nothing
        End If
    Catch ex As Exception
        Return Nothing
    End Try
End Function

And to illustrate its effect:

Shared Sub TestTryCastInteger()
    Dim temp As Integer?

    Dim OnePointTwo As Object = "1.2"
    temp = TryCastInteger(OnePointTwo)
    If temp Is Nothing Then
        Console.WriteLine("Could not convert to Integer")
    Else
        Console.WriteLine("TryCastInteger converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    End If

    Dim NotANumber As Object = "bob's your uncle"
    temp = TryCastInteger(NotANumber)
    If temp Is Nothing Then
        Console.WriteLine("Could not convert to Integer")
    Else
        Console.WriteLine("TryCastInteger converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    End If
End Sub

Running TestTryCastInteger() will output:

    TryCastInteger converted to: 1 (type: System.Int32)
    Could not convert to Integer

There also is such a thing as a null/Nothing Integer, or any other static type, called a "nullable" type, see Variable declaration question mark for some more information. But that does not really make it a "reference" type either.

3 Comments

-1 for "the equivalent to TryCast is CType". Not really. The entire point of using TryCast is to avoid the possibility of generating an exception at runtime. CType will cause an exception, if the conversion fails. In addition, TryCast does not attempt the full range of conversions that CType attempts. The two are used quite differently. TryCast is a very strict (and fast) conversion: it attempts to "upcast" to a specific subclass. It is used when it was necessary to pass an instance as a more general base class. CType can do many more conversions -- which is good or bad ..
.. depending on the programmer's intent. It may attempt MUCH more expensive conversions, such as parsing a string. Its behavior can also be overloaded in custom classes, to do anything at all. But even beyond that, the issue in recommending it here, is that you don't have enough information about what OP has in mind. It is a risky recommendation, that could lead to subtle bugs. It really shouldn't be used to cast from "Object", unless a programmer simply doesn't care what is coming in, and what the result will be -- they just "want it to work". The old, unreliable, way of Basic programming.
In summary, Jonathan is correct, if one's goal is to write a reliable program. If one has no control over the incoming type, and is stuck with an Object declaration, and you are expecting a value type, then the safe way to proceed is to start testing the object's type. Decide what to do, once you know what type of object you have.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.