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

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.


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)


32

Convert.ToInt32 (myobject);

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


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

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
    }


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

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

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

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>();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.