Better way to cast object to int

Viewed 396696

This is probably trivial, but I can't think of a better way to do it. I have a COM object that returns a variant which becomes an object in C#. The only way I can get this into an int is

int test = int.Parse(string.Format("{0}", myobject))

Is there a cleaner way to do this? Thanks

11 Answers

You have several options:

  • (int) — Cast operator. Works if the object already is an integer at some level in the inheritance hierarchy or if there is an implicit conversion defined.

  • int.Parse()/int.TryParse() — For converting from a string of unknown format.

  • int.ParseExact()/int.TryParseExact() — For converting from a string in a specific format

  • Convert.ToInt32() — For converting an object of unknown type. It will use an explicit and implicit conversion or IConvertible implementation if any are defined.

  • as int? — Note the "?". The as operator is only for reference types, and so I used "?" to signify a Nullable<int>. The "as" operator works like Convert.To____(), but think TryParse() rather than Parse(): it returns null rather than throwing an exception if the conversion fails.

Of these, I would prefer (int) if the object really is just a boxed integer. Otherwise use Convert.ToInt32() in this case.

Note that this is a very general answer: I want to throw some attention to Darren Clark's response because I think it does a good job addressing the specifics here, but came in late and wasn't voted as well yet. He gets my vote for "accepted answer", anyway, for also recommending (int), for pointing out that if it fails (int)(short) might work instead, and for recommending you check your debugger to find out the actual runtime type.

The cast (int) myobject should just work.

If that gives you an invalid cast exception then it is probably because the variant type isn't VT_I4. My bet is that a variant with VT_I4 is converted into a boxed int, VT_I2 into a boxed short, etc.

When doing a cast on a boxed value type it is only valid to cast it to the type boxed. Foe example, if the returned variant is actually a VT_I2 then (int) (short) myObject should work.

Easiest way to find out is to inspect the returned object and take a look at its type in the debugger. Also make sure that in the interop assembly you have the return value marked with MarshalAs(UnmanagedType.Struct)

Convert.ToInt32(myobject);

This will handle the case where myobject is null and return 0, instead of throwing an exception.

Use Int32.TryParse as follows.

  int test;
  bool result = Int32.TryParse(value, out test);
  if (result)
  {
     Console.WriteLine("Sucess");         
  }
  else
  {
     if (value == null) value = ""; 
     Console.WriteLine("Failure");
  }

There's also TryParse.

From MSDN:

private static void TryToParse(string value)
   {
      int number;
      bool result = Int32.TryParse(value, out number);
      if (result)
      {
         Console.WriteLine("Converted '{0}' to {1}.", value, number);         
      }
      else
      {
         if (value == null) value = ""; 
         Console.WriteLine("Attempted conversion of '{0}' failed.", value);
      }
   }

Strange, but the accepted answer seems wrong about the cast and the Convert in the mean that from my tests and reading the documentation too it should not take into account implicit or explicit operators.

So, if I have a variable of type object and the "boxed" class has some implicit operators defined they won't work.

Instead another simple way, but really performance costing is to cast before in dynamic.

(int)(dynamic)myObject.

You can try it in the Interactive window of VS.

public class Test
{
  public static implicit operator int(Test v)
  {
    return 12;
  }
}

(int)(object)new Test() //this will fail
Convert.ToInt32((object)new Test()) //this will fail
(int)(dynamic)(object)new Test() //this will pass

You can first cast object to string and then cast the string to int; for example:

string str_myobject = myobject.ToString();
int int_myobject = int.Parse(str_myobject);

this worked for me.

int i = myObject.myField.CastTo<int>();
Related