Meilleure façon de convertir un objet en int

179

C'est probablement trivial, mais je ne peux pas penser à une meilleure façon de le faire. J'ai un objet COM qui renvoie une variante qui devient un objet en C #. La seule façon dont je peux obtenir cela dans un int est

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

Y a-t-il un moyen plus propre de faire cela? Merci

Steve
la source

Réponses:

362

Vous avez plusieurs options:

  • (int)- Opérateur de casting. Fonctionne si l'objet est déjà un entier à un certain niveau de la hiérarchie d'héritage ou si une conversion implicite est définie.

  • int.Parse()/int.TryParse() - Pour la conversion à partir d'une chaîne de format inconnu.

  • int.ParseExact()/int.TryParseExact() - Pour la conversion d'une chaîne dans un format spécifique

  • Convert.ToInt32() - Pour convertir un objet de type inconnu. Il utilisera une conversion explicite et implicite ou une implémentation IConvertible le cas échéant.

  • as int?- Noter la "?". L' asopérateur est uniquement pour les types de référence, et j'ai donc utilisé "?" pour signifier a Nullable<int>. L' asopérateur " " fonctionne comme Convert.To____(), mais pensez TryParse()plutôt que Parse(): il renvoie nullplutôt que de lancer une exception si la conversion échoue.

Parmi ceux-ci, je préférerais (int)que l'objet soit vraiment juste un entier encadré. Sinon, utilisez Convert.ToInt32()dans ce cas.

Notez que c'est une réponse très générale : je veux attirer l'attention sur la réponse de Darren Clark parce que je pense qu'elle fait du bon travail en abordant les détails ici, mais est arrivée tard et n'a pas encore été votée. Il obtient mon vote pour "réponse acceptée", de toute façon, pour avoir également recommandé (int), pour avoir signalé que si cela échouait, cela (int)(short)pourrait fonctionner à la place, et pour vous recommander de vérifier votre débogueur pour connaître le type d'exécution réel.

Joel Coehoorn
la source
J'ai trouvé un point qui n'était pas vraiment une erreur mais qui simplifiait peut-être trop les choses pour que quelqu'un puisse le penser. J'ai supprimé cette phrase et ajouté un lien vers une documentation faisant autorité.
Joel Coehoorn
La distribution directe fonctionnera-t-elle avec une conversion implicite? J'avais l'impression que cela ne concernerait strictement que le déballage, pas d'autres conversions.
Darren Clark
Pas exactement une réponse, mais lisez ceci: blogs.msdn.com/ericlippert/archive/2009/03/19
Joel Coehoorn
Le résultat est qu'il fait certainement plus que déballer. Sinon, pourquoi pourriez-vous l'utiliser pour convertir un double en un entier, par exemple?
Joel Coehoorn
Et en lisant d'autres choses, je peux avoir mon implicite / explicite à l'envers là-haut - mais de toute façon, je pense que cela fait passer le message.
Joel Coehoorn
41

Le casting (int) myobject devrait juste fonctionner.

Si cela vous donne une exception de conversion non valide, c'est probablement parce que le type de variante n'est pas VT_I4. Mon pari est qu'une variante avec VT_I4 est convertie en un int boxed, VT_I2 en boxed short, etc.

Lorsque vous effectuez un cast sur un type de valeur encadré, il est uniquement valide de le convertir en type encadré. Par exemple, si la variante retournée est en fait un VT_I2, cela (int) (short) myObjectdevrait fonctionner.

Le moyen le plus simple de le savoir est d'inspecter l'objet retourné et de regarder son type dans le débogueur. Assurez-vous également que dans l'assembly d'interopérabilité, vous avez la valeur de retour marquée avecMarshalAs(UnmanagedType.Struct)

Darren Clark
la source
32

Convert.ToInt32 (monobjet);

cela gérera le cas où myobject est nul et retournera 0, au lieu de lever une exception.

Zahir J
la source
J'obtiens "Impossible de résoudre le symbole 'ToInt'" lorsque je l'essaye comme ça. Cela ne fonctionne que si j'utilise par exemple ToInt32.
Tobias Feil
Où pouvons-nous trouver cette méthode? Est-il dans la bibliothèque .Net Framework?
Amir Pourmand امیر پورمند
8

Utilisez Int32.TryParsecomme suit.

  int test;
  bool result = Int32.TryParse(value, out test);
  if (result)
  {
     Console.WriteLine("Sucess");         
  }
  else
  {
     if (value == null) value = ""; 
     Console.WriteLine("Failure");
  }
Srikar Doddi
la source
En fait, Parse appelle TryParse et lève une exception si TryParse renvoie false. TryParse ne gère donc pas l'exception car il n'en lance jamais.
Samuel
Eh bien, techniquement, ils appellent tous les deux la même méthode NumberToInt32, mais seul Parse lève des exceptions lorsque cela ne fonctionne pas.
Samuel
TryParse nécessite toujours la conversion du variant en chaîne. AFAIK, le problème n'est pas de convertir une chaîne en un entier, mais une variante qui est un int en un entier réel.
Darren Clark
3

J'énumère la différence dans chacun des modes de casting. Quel type particulier de poignées de moulage et ce n'est pas le cas?

    // 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
la source
2

Peut-être Convert.ToInt32 .

Attention aux exceptions, dans les deux cas.

JW
la source
2
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
Tohid
la source
1
J'ai trouvé cette réponse vraiment utile, je cherchais à convertir un octet encadré dans un int, et je l'ai fait fonctionner en utilisant Convert.ChangeType. Je dirais que ce n'est peut-être pas la réponse parfaite pour OP, mais c'est vraiment utile pour certains!
Philippe Paré
1

Il y a aussi TryParse .

Depuis 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
la source
1

Étrange, mais la réponse acceptée semble erronée à propos de la distribution et de la conversion en ce sens que d'après mes tests et la lecture de la documentation, elle ne devrait pas prendre en compte les opérateurs implicites ou explicites.

Donc, si j'ai une variable de type object et que la classe "boxed" a des opérateurs implicites définis, ils ne fonctionneront pas.

Au lieu de cela, un autre moyen simple, mais en réalité, le coût des performances consiste à lancer avant en dynamique.

(int) (dynamique) monObjet.

Vous pouvez l'essayer dans la fenêtre interactive 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
la source
1
c'est vrai , mais c'est certainement quelque chose que vous voudriez profiler si vous le faites beaucoup - dynamicc'est loin d'être gratuit
Marc Gravell
@MarcGravell Je suis totalement d'accord avec vous, comme je l'ai également écrit dans la réponse.
eTomm le
0
int i = myObject.myField.CastTo<int>();
Nae
la source