Wie kann man nach "sicheren" Conversions zwischen Werttypen in .NET überprüfen?

StackOverflow https://stackoverflow.com/questions/2124171

  •  22-09-2019
  •  | 
  •  

Frage

Zurück zu den Grundlagen...

Als Referenztypen kann man dies tun:

        SomeType someObject = firstObject as SomeType;
        if (someObject == null)
        {
            // Handle the situation gracefully
        }
        else
        {
            // Do stuff
        }

Mein Verständnis für Werttypen ist, dass wir implizite Konvertierungen (kein Datenverlust), explizite Conversions (erforderlich, wenn das Risiko eines Datenverlusts besteht), die Convert Klasse (ein "Conversion Wrapper", denke ich) und auch typspezifische Konvertierungen (z. B. double x = Double.Parse("2");), aber ich habe nichts ähnliches wie das gefunden as Operator oben.

Meine Frage lautet also: Hat das Framework eine Methode/Operator/Technik, um etwas in diesem Sinne zu tun:

        if (!Convert.CanConvert(someValue, someValueType))
        {
            // Beware! Data loss can occur
        }
        else
        {
            // No data loss here
        }

Wenn nicht, kann jemand da draußen einen soliden Ansatz vorschlagen, um einen solchen zu bauen CanConvert Methode?

Danke vielmals!

Bearbeiten (1): Das Benutzerfall/das Problem lautet wie folgt: gegeben a etwas vom Verbraucher des Kodex (mein anderes Selbst, aber das ist irrelevant), (1) das überprüfen etwas ist eine Zahl (einfach genug) und (2) Ort etwas im "kleinsten" numerischen Typ, bei dem er ohne Datenverlust passt.

Ein Hintergrund: Die Natur dessen, was ich versuche, ist mathematischer als technischer: Ich versuche zu sehen, ob/wie ich vorhandene numerische Typen in eine Art algebraische Hierarchie des Formulars monoid => Group => passen kann Ring => Feld (oder eine vereinfachte Version davon). Während der Arbeit daran und nicht sehr sicher, wie "eine Sache zum anderen führte" und ich mussten mit Typ Conversions umgehen ...

War es hilfreich?

Lösung

Wie wäre es mit der TryParse -Methode für die verschiedenen Werttypen?

int x;

if (int.TryParse(someType.ToString(), out x))
    return x;

Andere Tipps

Henk ist so ziemlich das Geld. Ich möchte seiner Antwort etwas hinzufügen, wenn ich:

Mehrwerttyp-Konvertierung im .NET-Framework funktioniert mit dem IConvertible Schnittstelle. Das Convert Die Klasse nutzt dies für fast alle seine Methoden. Dies unterscheidet sich stark von impliziten/expliziten Conversion -Operatoren in C#, die lediglich eine andere Form von syntaktischem Zucker sind.

Wenn Sie das schreiben:

public struct Duck
{
    public static implicit operator Goose(Duck d)
    {
        ...
    }
}

Das .NET -Framework selbst hat keine Ahnung Das existiert das. Es wird als ein emittiert op_implicit Und es liegt an der kompilierten Sprache, herauszufinden, wie man sie benutzt. Nicht jede MSIL -Sprache unterstützt diese tatsächlich. Dieser Code funktioniert also:

Goose g1 = duck;

Dieser Code nicht:

Goose g1 = (Goose)Convert.ChangeType(duck, typeof(Goose));

Um a zu implementieren CanConvert Methode, die implizite/explizit op_ Methoden, und ich müsste dagegen empfehlen - ich kann in der Praxis wenig dafür eingesetzt werden.

Sich ansehen Convert.ChangeType. Sie könnten das entführen, um Ihre Zwecke zu erfüllen, obwohl es langsam wäre, weil es ausnahmbar ist, zu werfen und zu doppelte, um die Konvertierung zu werfen.

Das Schlüsselwort "As" ist im Grunde genommen ein sicherer Downcast. Da alle Werttypen versiegelt sind, können sie nicht geerbt werden.

Ihr Code wäre also:

if (firstObject is MyValueType)
{
   MyValueType obj = (MyValueType) firstObject;
}
else
{
}

Ich denke, Sie verstehen den Punkt des AS -Operators Missverständnis. Der AS -Operator entspricht ungefähr dem folgenden Code:

if (firstObject is SomeType)
  return (SomeType)firstObject;
else
  return null;

Also wie eher eine Erbschaftsprüfung. (Wie die Liste implementiert ilist)

Werttypen unterstützen das Vererbung nicht und aus gutem Grund. Double und INT64 speichern beide die Nummer 1 in völlig unterschiedlichen Manieren.

Grundsätzlich möchten Sie eine Methode, die Sie für Sie bestimmt, ob eine Zahlenkonvertierung locker ist oder nicht. Nun, ich kontrolle mit "Warum?". Während das CLR einige Formate gibt, sind die Conversion -Regeln normalerweise ziemlich einfach. Zum Beispiel ist INT32 -> Double verlustlos, und jede Konvertierung von einem "kleineren" zu einem "größeren" ist verlustlos wie SByte -> INT64.

Eine andere Frage ist, was würde ein Falsch in Ihrem Beispiel bedeuten? Ich würde zum Beispiel sehr wenig sagen:

Convert.CanConvert(123456789.12345F, typeof(Byte))

Was nützt das falsche Ergebnis? Sie implizieren, dass es für Fälle wie Int32 -> Single ist, in denen einige Daten verloren gehen würden, aber in diesem Fall geht eine Menge Daten verloren, da die "engste" Byte -Darstellung 255 ist.

Aufgrund dieser beiden Probleme gibt es keine solche Methode.

Das as Der Bediener basiert auf der Vererbung und Werttypen erben nicht. Sie könnten wahrscheinlich eine schreiben CanConvert() Aber es müsste mit Box -Wertetypen funktionieren, und Sie möchten normalerweise das Boxen vermeiden.

Also, möglich: Ja, wünschenswert: Nein.

Vielleicht können Sie ein Anwendungsszenario hinzufügen, in dem Sie dies verwenden möchten, und dann können wir Alternativen empfehlen.

Betreff: Bearbeiten (1)

Ich hoffe, Sie wissen, dass das System numerischer Typen größtenteils historisches Gepäck ist und nicht sehr logische Regeln folgt. Es gibt zum Beispiel kein short Berechnung, sie werden immer in INT konvertiert, bevor sie etwas tun.

Aber vielleicht können Sie dieses Verhalten in Bezug auf Ring und Feld definieren, dass Algebra für mich ein "langjähriger Übergang" war.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top