Mejor manera de lanzar objetos a int

179

Esto es probablemente trivial, pero no puedo pensar en una mejor manera de hacerlo. Tengo un objeto COM que devuelve una variante que se convierte en un objeto en C #. La única forma en que puedo llevar esto a un int es

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

¿Hay una forma más limpia de hacer esto? Gracias

Steve
fuente

Respuestas:

362

Tienes varias opciones:

  • (int)- Operador de reparto. Funciona si el objeto ya es un número entero en algún nivel de la jerarquía de herencia o si hay una conversión implícita definida.

  • int.Parse()/int.TryParse() - Para convertir desde una cadena de formato desconocido.

  • int.ParseExact()/int.TryParseExact() - Para convertir desde una cadena en un formato específico

  • Convert.ToInt32() - Para convertir un objeto de tipo desconocido. Utilizará una conversión explícita e implícita o una implementación de IConvertible si hay alguna definida.

  • as int?- Nota la "?". El asoperador es solo para tipos de referencia, así que usé "?" significar a Nullable<int>. El " as" operador funciona como Convert.To____(), pero piensa en TryParse()lugar de Parse(): regresa en nulllugar de lanzar una excepción si la conversión falla.

De estos, preferiría (int)si el objeto realmente es solo un entero en caja. De lo contrario, use Convert.ToInt32()en este caso.

Tenga en cuenta que esta es una respuesta muy general : quiero llamar la atención sobre la respuesta de Darren Clark porque creo que hace un buen trabajo al abordar los detalles aquí, pero llegó tarde y todavía no fue votado. De todos modos, obtiene mi voto para "respuesta aceptada", también por recomendar (int), señalar que si falla (int)(short)podría funcionar en su lugar, y por recomendarle que verifique su depurador para averiguar el tipo de tiempo de ejecución real.

Joel Coehoorn
fuente
Encontré un punto que no era realmente un error, pero quizás simplificó demasiado las cosas para que alguien pudiera pensar eso. Eliminé esa oración y agregué un enlace a la documentación autorizada.
Joel Coehoorn el
¿Funcionará el elenco directo con una conversión implícita? Tenía la impresión de que eso solo haría unboxing estrictamente, no otras conversiones.
Darren Clark el
No es exactamente una respuesta, pero lea esto: blogs.msdn.com/ericlippert/archive/2009/03/19/…
Joel Coehoorn el
El resultado es que definitivamente hace más que simplemente desempacar. De lo contrario, ¿por qué podría usarlo para lanzar un doble a un int, por ejemplo?
Joel Coehoorn el
Y al leer algunas otras cosas, puedo tener mi implícito / explícito al revés, pero de cualquier manera creo que se entiende.
Joel Coehoorn el
41

El elenco (int) myobject debería funcionar.

Si eso le da una excepción de conversión no válida, probablemente se deba a que el tipo de variante no es VT_I4. Mi apuesta es que una variante con VT_I4 se convierte en un cuadro int, VT_I2 en un cuadro corto, etc.

Al realizar una conversión en un tipo de valor en recuadro, solo es válido emitirlo en el tipo encuadrado. Ejemplo de enemigo, si la variante devuelta es en realidad un VT_I2, entonces(int) (short) myObject debería funcionar.

La forma más fácil de averiguarlo es inspeccionar el objeto devuelto y observar su tipo en el depurador. También asegúrese de que en el ensamblaje de interoperabilidad tenga el valor de retorno marcado conMarshalAs(UnmanagedType.Struct)

Darren Clark
fuente
32

Convert.ToInt32 (myobject);

esto manejará el caso donde myobject es nulo y devolverá 0, en lugar de lanzar una excepción.

Zahir J
fuente
Aparece el mensaje "No se puede resolver el símbolo 'ToInt'" cuando lo intento así. Solo funciona si uso eg ToInt32.
Tobias Feil
¿Dónde podemos encontrar este método? ¿Está en .Net Framework Library?
Amir Pourmand امیر پورمند
8

Use de la Int32.TryParsesiguiente manera.

  int test;
  bool result = Int32.TryParse(value, out test);
  if (result)
  {
     Console.WriteLine("Sucess");         
  }
  else
  {
     if (value == null) value = ""; 
     Console.WriteLine("Failure");
  }
Srikar Doddi
fuente
En realidad, Parse llama a TryParse y lanza una excepción si TryParse devuelve falso. Entonces TryParse no maneja la excepción porque nunca arroja una.
Samuel
Bueno, técnicamente ambos llaman al mismo método NumberToInt32, pero solo Parse lanza excepciones cuando no funciona.
Samuel
TryParse aún requiere convertir la variante a una cadena. AFAIK el problema no es convertir de una cadena a un int, sino de una variante que es un int a un int real.
Darren Clark el
3

Estoy enumerando la diferencia en cada una de las formas de casting. ¿Qué tipo particular de fundición maneja y no maneja?

    // 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
fuente
2
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
Esconder
fuente
1
Encontré esta respuesta realmente útil, estaba buscando convertir un byte en caja en un int, y lo puse a trabajar usando Convert.ChangeType. Diría que podría no ser la respuesta perfecta para OP, ¡pero definitivamente es útil para algunos!
Philippe Paré
1

También hay TryParse .

De 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
fuente
1

Es extraño, pero la respuesta aceptada parece incorrecta sobre el elenco y la conversión en el sentido de que, a partir de mis pruebas y la lectura de la documentación, no debería tener en cuenta los operadores implícitos o explícitos.

Entonces, si tengo una variable de tipo objeto y la clase "en caja" tiene algunos operadores implícitos definidos, no funcionarán.

En cambio, otra forma simple, pero realmente el costo del rendimiento es lanzar antes en forma dinámica.

(int) (dinámico) myObject.

Puede probarlo en la ventana interactiva de 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
fuente
1
esto es cierto , pero definitivamente es algo que desearías perfilar si lo estás haciendo mucho, dynamicestá lejos de ser gratuito
Marc Gravell
@MarcGravell Estoy totalmente de acuerdo contigo, como también escribí en la respuesta.
eTomm
0
int i = myObject.myField.CastTo<int>();
Nae
fuente