Melhor maneira de converter objetos para int


179

Provavelmente isso é trivial, mas não consigo pensar em uma maneira melhor de fazê-lo. Eu tenho um objeto COM que retorna uma variante que se torna um objeto em c #. A única maneira de colocar isso em um int é

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

Existe uma maneira mais limpa de fazer isso? obrigado

Respostas:


362

Você tem várias opções:

  • (int)- Operador de elenco. Funciona se o objeto já for um número inteiro em algum nível na hierarquia de herança ou se houver uma conversão implícita definida.

  • int.Parse()/int.TryParse() - Para converter de uma sequência de formato desconhecido.

  • int.ParseExact()/int.TryParseExact() - Para converter de uma string em um formato específico

  • Convert.ToInt32() - Para converter um objeto de tipo desconhecido. Ele usará uma conversão explícita e implícita ou implementação IConvertible, se houver alguma definida.

  • as int?- Note o "?". O asoperador é apenas para tipos de referência e, portanto, usei "?" para significar a Nullable<int>. O asoperador " " funciona como Convert.To____(), mas pense em TryParse()vez de Parse(): retorna em nullvez de lançar uma exceção se a conversão falhar.

Destes, eu preferiria (int)se o objeto realmente fosse apenas um número inteiro em caixa. Caso contrário, useConvert.ToInt32() neste caso.

Observe que esta é uma resposta muito geral : quero chamar a atenção para a resposta de Darren Clark porque acho que ele faz um bom trabalho abordando os detalhes aqui, mas chegou tarde e ainda não foi votado. De qualquer forma, ele recebe meu voto para "resposta aceita" por também recomendar (int), por apontar que, se falhar, (int)(short)pode funcionar e por recomendar que você verifique seu depurador para descobrir o tipo de tempo de execução real.


Eu encontrei um ponto que não era realmente um erro, mas talvez tenha simplificado demais as coisas para que alguém possa pensar isso. Eu removi essa frase e adicionei um link à documentação autorizada.
Joel Coehoorn

O elenco direto funcionará com uma conversão implícita? Fiquei com a impressão de que isso estritamente fará unboxing, não outras conversões.
11139 Darren Clark

Não é exatamente uma resposta, mas leia isto: blogs.msdn.com/ericlippert/archive/2009/03/19/…
Joel Coehoorn

O resultado é que ele definitivamente faz mais do que apenas descompactar. Caso contrário, por que você poderia usá-lo para converter um dobro em um int, por exemplo?
Joel Coehoorn

E lendo algumas outras coisas, posso ter meu implícito / explícito ao contrário - mas, de qualquer maneira, acho que isso esclarece.
Joel Coehoorn

41

O elenco (int) myobject deve funcionar.

Se isso der uma exceção de conversão inválida, provavelmente é porque o tipo de variante não é VT_I4. Minha aposta é que uma variante com VT_I4 seja convertida em um int em caixa, VT_I2 em um short em caixa, etc.

Ao fazer uma conversão em um tipo de valor em caixa, é válido apenas convertê-lo no tipo em caixa. Por exemplo, se a variante retornada for realmente um VT_I2,(int) (short) myObject deverá funcionar.

A maneira mais fácil de descobrir é inspecionar o objeto retornado e dar uma olhada no seu tipo no depurador. Verifique também se no assembly de interoperabilidade você tem o valor de retorno marcado comMarshalAs(UnmanagedType.Struct)


32

Convert.ToInt32 (myobject);

isso tratará do caso em que myobject é nulo e retorna 0, em vez de gerar uma exceção.


Recebo "Não é possível resolver o símbolo 'ToInt'" quando tento dessa maneira. Só funciona se eu usar, por exemplo ToInt32.
Tobias Feil

Onde podemos encontrar esse método? Está na .Net Framework Library?
Amir Pourmand ام

8

Use da Int32.TryParseseguinte maneira.

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

Na verdade, o Parse chama TryParse e lança uma exceção se TryParse retornar false. Portanto, o TryParse não lida com a exceção porque nunca lança uma.
31510 Samuel Samuel

Bem, tecnicamente, os dois chamam o mesmo método NumberToInt32, mas apenas o Parse lança exceções quando não funciona.
Samuel

O TryParse ainda requer a conversão da variante em uma string. AFAIK, o problema não está sendo convertido de uma sequência para um int, mas de uma variante que é um int para um int real.
11139 Darren Clark

3

Estou listando a diferença em cada uma das formas de elenco. Que tipo específico de fundição manipula e não funciona?

    // 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
Achei essa resposta realmente útil, estava procurando converter um byte in box em um int e consegui usá-lo Convert.ChangeType. Eu diria que pode não ser a resposta perfeita para o OP, mas é definitivamente útil para alguns!
Philippe Paré

1

Há também TryParse .

Do 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

Estranho, mas a resposta aceita parece errada sobre o elenco e o Convert, pois nos meus testes e na leitura da documentação também não devemos levar em consideração operadores implícitos ou explícitos.

Portanto, se eu tiver uma variável do tipo objeto e a classe "box" tiver alguns operadores implícitos definidos, eles não funcionarão.

Em vez disso, outra maneira simples, mas realmente o custo do desempenho, é converter antes em dinâmico.

(int) (dinâmico) myObject.

Você pode experimentá-lo na janela interativa do 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
isso é verdade , mas é definitivamente algo que você gostaria de perfil se você está fazendo isso muito - dynamicestá longe de ser livre
Marc Gravell

@ MarcGravell Eu concordo totalmente com você, como também escrevi na resposta.
eTomm

0
int i = myObject.myField.CastTo<int>();
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.