196

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

Steve
  • 11,197
  • 13
  • 66
  • 98

11 Answers11

399

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.

Joel Coehoorn
  • 362,140
  • 107
  • 528
  • 764
  • I did find a point that wasn't really an error but perhaps simplified things too much so someone might think that. I've removed that sentence and added a link to authoritative documentation. – Joel Coehoorn Apr 13 '09 at 20:28
  • Will the direct cast work with an implicit conversion? I was under the impression that that will strictly do unboxing only, not any other conversions. – Darren Clark Apr 13 '09 at 20:59
  • Not exactly a response, but read this: http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx – Joel Coehoorn Apr 13 '09 at 21:12
  • The upshot is that it definitely does more than just unbox. Otherwise why could you use it to cast a double to an int, for example? – Joel Coehoorn Apr 13 '09 at 21:13
  • And reading some other things I may have my implicit/explicit backwards up there- but either way I think it gets the point across. – Joel Coehoorn Apr 13 '09 at 21:21
  • I meant specifically the cast from ref to value type, not in general. That's why the (int) (short) works, one unbox, one explicit cast. Actually I think int val = (short) myObject should work since a cast from short to int is implicit. – Darren Clark Apr 13 '09 at 21:31
  • instead of "as int" (which won't compile) you could try "as int?" – Jimmy Jun 05 '09 at 21:01
  • `Int32` doesn't seem to have `ParseExact` or `TryParseExact`. – Sam Dec 17 '13 at 06:09
42

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)

Liam
  • 22,818
  • 25
  • 93
  • 157
Darren Clark
  • 2,755
  • 17
  • 14
34
Convert.ToInt32(myobject);

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

Pang
  • 8,605
  • 144
  • 77
  • 113
Zahir J
  • 906
  • 8
  • 15
9

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");
  }
Samuel
  • 35,821
  • 11
  • 83
  • 84
Srikar Doddi
  • 15,091
  • 15
  • 60
  • 106
  • Actually, Parse calls TryParse and throws an exception if TryParse returns false. So TryParse doesn't handle the exception because it never throws one. – Samuel Apr 13 '09 at 20:20
  • Well technically they both call the same method NumberToInt32, but only Parse throws exceptions when it doesn't work. – Samuel Apr 13 '09 at 20:22
  • TryParse still requires converting the variant to a string. AFAIK the issue isn't converting from a string to an int, but from a variant that is an int to an actual int. – Darren Clark Apr 13 '09 at 20:44
3

I am listing the difference in each of the casting ways. What a particular type of casting handles and it doesn't?

    // object to int
    // does not handle null
    // does not handle NAN ("102art54")
    // convert value to integar
    int intObj = (int)obj;

    // handles only null or number
    int? nullableIntObj = (int?)obj; // null
    Nullable<int> nullableIntObj1 = (Nullable<int>)obj; // null

   // best way for casting from object to nullable int
   // handles null 
   // handles other datatypes gives null("sadfsdf") // result null
    int? nullableIntObj2 = obj as int?; 

    // string to int 
    // does not handle null( throws exception)
    // does not string NAN ("102art54") (throws exception)
    // converts string to int ("26236")
    // accepts string value
    int iVal3 = int.Parse("10120"); // throws exception value cannot be null;

    // handles null converts null to 0
    // does not handle NAN ("102art54") (throws exception)
    // converts obj to int ("26236")
    int val4 = Convert.ToInt32("10120"); 

    // handle null converts null to 0
    // handle NAN ("101art54") converts null to 0
    // convert string to int ("26236")
    int number;

    bool result = int.TryParse(value, out number);

    if (result)
    {
        // converted value
    }
    else
    {
        // number o/p = 0
    }
Nayas Subramanian
  • 1,901
  • 16
  • 24
2
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
Tohid
  • 5,185
  • 7
  • 42
  • 75
  • 1
    I found this answer really useful, I was looking to cast a boxed byte into an int, and got it to work using `Convert.ChangeType`. I would says might not be the perfect answer for OP, but It's definitely helpful to some! – Philippe Paré Jan 19 '17 at 14:31
2

Maybe Convert.ToInt32.

Watch out for exception, in both cases.

J.W.
  • 16,815
  • 6
  • 40
  • 75
1

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
eTomm
  • 31
  • 1
1

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);
      }
   }
Lance Harper
  • 2,170
  • 13
  • 10
0
int i = myObject.myField.CastTo<int>();
Nae
  • 10,363
  • 4
  • 30
  • 67
0

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.