Besserer Weg, um ein Objekt in int zu verwandeln


178

Das ist wahrscheinlich trivial, aber ich kann mir keinen besseren Weg vorstellen, es zu tun. Ich habe ein COM-Objekt, das eine Variante zurückgibt, die in C # zu einem Objekt wird. Der einzige Weg, wie ich das in ein int bringen kann, ist

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

Gibt es einen saubereren Weg, dies zu tun? Vielen Dank

Antworten:


361

Sie haben mehrere Möglichkeiten:

  • (int)- Cast Operator. Funktioniert, wenn das Objekt auf einer bestimmten Ebene in der Vererbungshierarchie bereits eine Ganzzahl ist oder wenn eine implizite Konvertierung definiert ist.

  • int.Parse()/int.TryParse() - Zum Konvertieren von einer Zeichenfolge unbekannten Formats.

  • int.ParseExact()/int.TryParseExact() - Zum Konvertieren von einer Zeichenfolge in einem bestimmten Format

  • Convert.ToInt32() - Zum Konvertieren eines Objekts unbekannten Typs. Es wird eine explizite und implizite Konvertierung oder eine IConvertible-Implementierung verwendet, falls vorhanden.

  • as int?- Beachten Sie das "?". Der asOperator ist nur für Referenztypen und deshalb habe ich "?" a Nullable<int>. Der asOperator " " funktioniert wie Convert.To____(), denkt aber TryParse()eher als Parse(): Er gibt zurück, nullanstatt eine Ausnahme auszulösen, wenn die Konvertierung fehlschlägt.

Von diesen würde ich es vorziehen, (int)wenn das Objekt wirklich nur eine Ganzzahl in einer Box ist. Andernfalls Convert.ToInt32()in diesem Fall verwenden.

Beachten Sie, dass dies eine sehr allgemeine Antwort ist: Ich möchte etwas Aufmerksamkeit auf Darren Clarks Antwort lenken, da ich denke, dass sie gute Arbeit leistet, um die Einzelheiten hier anzusprechen , aber zu spät gekommen ist und noch nicht gewählt wurde. Er erhält meine Stimme für "akzeptierte Antwort", weil er (int) empfohlen hat, darauf hingewiesen hat, dass ein Fehler (int)(short)möglicherweise stattdessen funktioniert, und weil er empfohlen hat, Ihren Debugger zu überprüfen, um den tatsächlichen Laufzeittyp herauszufinden.


Ich habe einen Punkt gefunden, der nicht wirklich ein Fehler war, aber vielleicht die Dinge zu stark vereinfacht hat, damit jemand das denken könnte. Ich habe diesen Satz entfernt und einen Link zur maßgeblichen Dokumentation hinzugefügt.
Joel Coehoorn

Funktioniert die direkte Besetzung mit einer impliziten Konvertierung? Ich hatte den Eindruck, dass dies ausschließlich das Unboxing und keine anderen Conversions ermöglicht.
Darren Clark

Nicht gerade eine Antwort, aber lesen Sie diese: blogs.msdn.com/ericlippert/archive/2009/03/19/…
Joel Coehoorn

Das Ergebnis ist, dass es definitiv mehr als nur Unbox macht. Warum könnten Sie es sonst zum Beispiel verwenden, um ein Double in ein Int umzuwandeln?
Joel Coehoorn

Und wenn ich einige andere Dinge lese, habe ich vielleicht mein implizites / explizites Rückwärts - aber so oder so denke ich, bringt es den Punkt rüber.
Joel Coehoorn

41

Die Besetzung (int) myobject sollte einfach funktionieren.

Wenn dies zu einer ungültigen Besetzungsausnahme führt, liegt dies wahrscheinlich daran, dass der Variantentyp nicht VT_I4 ist. Ich wette, dass eine Variante mit VT_I4 in ein Boxed Int, VT_I2 in ein Boxed Short usw. umgewandelt wird.

Wenn Sie einen Casting-Wert für einen Boxed-Value-Typ ausführen, ist es nur gültig, ihn in den Boxed-Typ umzuwandeln. Feind Beispiel, wenn die zurückgegebene Variante tatsächlich ein VT_I2 ist, (int) (short) myObjectsollte funktionieren.

Der einfachste Weg, dies herauszufinden, besteht darin, das zurückgegebene Objekt zu untersuchen und seinen Typ im Debugger zu überprüfen. Stellen Sie außerdem sicher, dass in der Interop-Assembly der Rückgabewert mit markiert istMarshalAs(UnmanagedType.Struct)


32

Convert.ToInt32 (myobject);

Dies behandelt den Fall, in dem myobject null ist und 0 zurückgibt, anstatt eine Ausnahme auszulösen.


Ich erhalte die Meldung "Symbol 'ToInt' kann nicht aufgelöst werden", wenn ich es so versuche. Es funktioniert nur, wenn ich zB benutze ToInt32.
Tobias Feil

Wo finden wir diese Methode? Befindet es sich in der .Net Framework Library?
Amir Pourmand امیر پورمند

8

Verwenden Sie Int32.TryParsewie folgt.

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

Tatsächlich ruft Parse TryParse auf und löst eine Ausnahme aus, wenn TryParse false zurückgibt. TryParse behandelt die Ausnahme also nicht, da sie niemals eine auslöst.
Samuel

Technisch gesehen rufen beide dieselbe Methode NumberToInt32 auf, aber nur Parse löst Ausnahmen aus, wenn dies nicht funktioniert.
Samuel

TryParse erfordert weiterhin die Konvertierung der Variante in einen String. AFAIK das Problem konvertiert nicht von einer Zeichenfolge in eine int, sondern von einer Variante, die eine int in eine tatsächliche int ist.
Darren Clark

3

Ich liste den Unterschied in jeder der Casting-Möglichkeiten auf. Was für eine bestimmte Art von Gussgriffen und nicht?

    // 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
Ich fand diese Antwort wirklich nützlich. Ich wollte ein Box-Byte in ein Int umwandeln und es zum Laufen bringen Convert.ChangeType. Ich würde sagen, dass dies möglicherweise nicht die perfekte Antwort für OP ist, aber es ist definitiv hilfreich für einige!
Philippe Paré

1

Es gibt auch TryParse .

Von 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

Seltsam, aber die akzeptierte Antwort scheint in Bezug auf die Besetzung und den Konvertieren falsch zu sein, da meine Tests und das Lesen der Dokumentation implizite oder explizite Operatoren nicht berücksichtigen sollten.

Wenn ich also eine Variable vom Typ Objekt habe und in der Klasse "boxed" einige implizite Operatoren definiert sind, funktionieren sie nicht.

Stattdessen ist ein anderer einfacher Weg, aber wirklich Leistungskosten, vorher in dynamisch zu gießen.

(int) (dynamisch) myObject.

Sie können es im interaktiven Fenster von VS versuchen.

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
Dies ist wahr , aber definitiv etwas, das Sie profilieren möchten, wenn Sie viel tun - dynamicist
alles andere als

@MarcGravell Ich stimme dir vollkommen zu, wie ich auch in der Antwort geschrieben habe.
eTomm

0
int i = myObject.myField.CastTo<int>();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.