2009-04-13 17 views
122

Questo è probabilmente banale, ma non riesco a pensare a un modo migliore per farlo. Ho un oggetto COM che restituisce una variante che diventa un oggetto in C#. L'unico modo per ottenerlo in un numero intero èUn modo migliore per trasmettere l'oggetto a int

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

Esiste un modo più semplice per fare ciò? Grazie

risposta

266

sono disponibili diverse opzioni: operatore

  • (int) — Cast. Funziona se l'oggetto è già un numero intero a un determinato livello nella gerarchia dell'ereditarietà o se è stata definita una conversione implicita.

  • int.Parse()/int.TryParse() — Per la conversione da una stringa di formato sconosciuto.

  • int.ParseExact()/int.TryParseExact() — Per la conversione da una stringa in un formato specifico

  • Convert.ToInt32() — Per convertire un oggetto di tipo sconosciuto. Utilizzerà una conversione esplicita e implicita o un'implementazione IConvertible se ne sono definiti alcuni.

  • as int? — Nota "?". L'operatore as è solo per i tipi di riferimento e quindi ho usato "?" per indicare un Nullable<int>. L'operatore "as" funziona come Convert.To____() ma pensa a TryParse() anziché a Parse(): restituisce null anziché generare un'eccezione se la conversione fallisce.

Di questi, preferirei (int) se l'oggetto è in realtà solo un intero in scatola. Altrimenti usare Convert.ToInt32() in questo caso.

Si noti che questo è un generale risposta: voglio lanciare una certa attenzione alla risposta di Darren Clark perché penso che fa un buon lavoro affrontare le specifiche qui, ma arrivato in ritardo e non è stato votato come bene ancora.Ottiene il mio voto per "risposta accettata", comunque, per raccomandare anche (int), per segnalare che se fallisce il (int)(short) potrebbe invece funzionare, e per raccomandare di controllare il debugger per scoprire il tipo effettivo di runtime.

+0

Ho trovato un punto che non era proprio un errore, ma forse ha semplificato le cose troppo, quindi qualcuno potrebbe pensarlo. Ho rimosso quella frase e aggiunto un link alla documentazione autorevole. –

+0

Il cast diretto funzionerà con una conversione implicita? Avevo l'impressione che ciò avvenga solo in modo unboxing, non in altre conversioni. –

+0

Non esattamente una risposta, ma leggi questo: http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx –

8

Utilizzare Int32.TryParse come segue.

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

In realtà, Parse chiama TryParse e genera un'eccezione se TryParse restituisce false. Quindi TryParse non gestisce l'eccezione perché non ne getta mai una. – Samuel

+0

Tecnicamente entrambi chiamano lo stesso metodo NumberToInt32, ma solo Parse genera eccezioni quando non funziona. – Samuel

+0

TryParse richiede ancora la conversione della variante in una stringa. AFAIK il problema non è la conversione da una stringa a un int, ma da una variante che è un int a un int reale. –

17
Convert.ToInt(myobject); 

Ciò gestire il caso in cui è myobjectnull e ritorno 0, invece di un'eccezione.

2

C'è anche TryParse.

Da 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); 
     } 
    } 
28

Il cast (int) MyObjectdovrebbe solo di lavoro.

Se ciò fornisce un'eccezione di cast non valida, probabilmente è perché il tipo di variante non è VT_I4. La mia scommessa è che una variante con VT_I4 viene convertita in un int inscatolato, VT_I2 in un boxed short, ecc.

Quando si esegue un cast su un valore di tipo boxed è valido solo per il cast nel tipo inserito. Esempio di esempio, se la variante restituita è in realtà un VT_I2 allora (int) (breve) myObject dovrebbe funzionare.

Il modo più semplice per scoprirlo è ispezionare l'oggetto restituito e dare un'occhiata al suo tipo nel debugger. Assicurarsi inoltre che nel assembly di interoperabilità si ha il valore di ritorno segnato con MarshalAs (UnmanagedType.Struct)

2
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?; 
+1

Ho trovato questa risposta davvero utile, stavo cercando di inserire un byte in un int in box, e ho funzionato usando 'Convert.ChangeType'. Direi che potrebbe non essere la risposta perfetta per OP, ma è sicuramente utile per alcuni! –

2

Sto elencando la differenza in ciascuno dei modi di fusione. Che tipo di maniglie di casting particolari e non lo fa?

// 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 
    } 
Problemi correlati