Modo migliore per trasmettere l'oggetto a int


179

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 ottenere questo in un int è

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

C'è un modo più pulito per farlo? Grazie

Risposte:


362

Hai diverse opzioni:

  • (int)- Operatore cast. Funziona se l'oggetto è già un numero intero a un certo 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 definite.

  • as int?- Notare la "?". L' asoperatore è solo per tipi di riferimento e quindi ho usato "?" per indicare a Nullable<int>. L' asoperatore " " funziona come Convert.To____(), ma pensa TryParse()piuttosto che Parse(): restituisce nullpiuttosto che generare un'eccezione se la conversione fallisce.

Di questi, preferirei (int)se l'oggetto fosse davvero solo un numero intero inscatolato. Altrimenti utilizzare Convert.ToInt32()in questo caso.

Si noti che questa è una risposta molto generale : voglio rivolgere un po 'di attenzione alla risposta di Darren Clark perché penso che faccia un buon lavoro affrontando i dettagli qui, ma è arrivato tardi e non è stato ancora votato. Ottiene il mio voto per "risposta accettata", comunque, per aver anche raccomandato (int), per aver sottolineato che in caso contrario (int)(short)potrebbe funzionare, e per raccomandarti di controllare il tuo debugger per scoprire il tipo di runtime effettivo.


Ho trovato un punto che in realtà non era un errore, ma forse le cose erano troppo semplificate, quindi qualcuno potrebbe pensarlo. Ho rimosso quella frase e ho aggiunto un link alla documentazione autorevole.
Joel Coehoorn

Il cast diretto funzionerà con una conversione implicita? Ho avuto l'impressione che ciò farà rigorosamente solo unboxing, non altre conversioni.
Darren Clark

Non esattamente una risposta, ma leggi questo: blogs.msdn.com/ericlippert/archive/2009/03/19/…
Joel Coehoorn

Il risultato è che sicuramente fa molto di più di unbox. Altrimenti perché potresti usarlo per lanciare un doppio in un int, per esempio?
Joel Coehoorn,

E leggendo alcune altre cose potrei avere il mio implicito / esplicito all'indietro lassù, ma in entrambi i casi penso che ottenga il punto.
Joel Coehoorn,

41

Il cast (int) myobject dovrebbe funzionare.

Se ciò ti dà 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 box int, VT_I2 in un box short, ecc.

Quando si esegue un cast su un tipo di valore inscatolato, è valido solo lanciarlo sul tipo inscatolato. Ad esempio, se la variante restituita è in realtà un VT_I2, (int) (short) myObjectdovrebbe funzionare.

Il modo più semplice per scoprirlo è ispezionare l'oggetto restituito e dare un'occhiata al suo tipo nel debugger. Assicurarsi inoltre che nell'assieme di interoperabilità si abbia il valore di ritorno contrassegnato conMarshalAs(UnmanagedType.Struct)


32

Convert.ToInt32 (myObject);

questo gestirà il caso in cui myobject è null e restituirà 0, anziché generare un'eccezione.


Ottengo "Impossibile risolvere il simbolo 'ToInt'" quando lo provo in questo modo. Funziona solo se uso ad es ToInt32.
Tobias Feil,

Dove possiamo trovare questo metodo? È nella libreria .Net Framework?
Amir Pourmand امیر پورمند

8

Utilizzare Int32.TryParsecome segue.

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

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

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

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

3

Sto elencando la differenza in ciascuno dei modi di casting. Quale particolare tipo di fusione gestisce 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
    }


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

1
Ho trovato questa risposta davvero utile, stavo cercando di lanciare un byte inscatolato in un int e farlo funzionare Convert.ChangeType. Direi che potrebbe non essere la risposta perfetta per OP, ma è sicuramente utile per alcuni!
Philippe Paré,

1

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

1

Strano, ma la risposta accettata sembra sbagliata riguardo al cast e al Convert nel senso che dai miei test e dalla lettura della documentazione non dovrebbe tener conto degli operatori impliciti o espliciti.

Quindi, se ho una variabile di tipo object e la classe "boxed" ha alcuni operatori impliciti definiti che non funzioneranno.

Invece un altro modo semplice, ma il costo delle prestazioni è quello di lanciare prima in modo dinamico.

(Int) (dinamica) myObject.

Puoi provarlo nella finestra interattiva di 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

1
questo è vero , ma è sicuramente qualcosa che vorresti profilare se lo stai facendo molto - dynamicè tutt'altro che gratuito
Marc Gravell

@MarcGravell Sono totalmente d'accordo con te, come ho anche scritto nella risposta.
eTomm,

0
int i = myObject.myField.CastTo<int>();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.