3 Stimmen

C# ?? kombiniert mit ?: Frage

Ich baue einen XML-Deserialisierer für ein Projekt und stoße recht häufig auf diese Art von Codesituation:

var myVariable = ParseNDecimal(xml.Element("myElement")) == null ? 
                 0 : ParseNDecimal(xml.Element("myElement")).Value;

Gibt es eine bessere Möglichkeit, diese Anweisung zu schreiben?

EDIT: Vielleicht sollte ich mein Beispiel konkretisieren, da ich eine Hilfsmethode zum Parsen des Strings in ein Dezimalzahl habe.

6voto

TcKs Punkte 24671

Sie können die Erweiterungsmethode verwenden:

public static T TryGetValue( this XmlElement element ) {
    if ( null == element ) return default(T);
    return (T)element.Value;
}
...
...
var myVariable = xml.Element("myElement").TryGetValue();

BEARBEITEN:

Die "universelle" Lösung:

static class Program {
    static void Main() {
        var xmlDecimal = new XElement( "decimal" );
        xmlDecimal.Value = ( 123.456m ).ToString();
        decimal valueOfDecimal_1 = xmlDecimal.ValueAs( decimal.TryParse );
        bool valueOfBool_1 = xmlDecimal.ValueAs( bool.TryParse );

        var xmlBool = new XElement( "bool" );
        xmlBool.Value = true.ToString();
        decimal valueOfDecimal_2 = xmlBool.ValueAs( decimal.TryParse );
        bool valueOfBool_2 = xmlBool.ValueAs( bool.TryParse );
    }
}

public static class StaticClass {
    public delegate bool TryParseDelegate( string text, out T value );
    public static T ValueAs( this XElement element, TryParseDelegate parseDelegate ) {
        return ValueAs( element, parseDelegate, default( T ) );
    }
    public static T ValueAs( this XElement element, TryParseDelegate parseDelegate, T defaultValue ) {
        if ( null == element ) { return defaultValue; }

        T result;
        bool ok = parseDelegate( element.Value, out result );
        if ( ok ) { return result; }

        return defaultValue;
    }
}

5voto

Jon Skeet Punkte 1325502

Bearbeiten: Angesichts der bearbeiteten Frage ist dies viel einfacher.

Es verwendet wieder eine Erweiterungsmethode, aber jetzt ist es nicht mehr nötig, eine Umwandlung in der Methode durchzuführen.

var myVariable = ParseNDecimal(xml.Element("myElement").ValueOrDefault("0"));

...

public static string ValueOrDefault(this XElement element, 
                                     string defaultValue)
{
    return element != null ? element.Value : defaultValue;
}

Wenn Ihnen die Methode mit einem String-Parameter nicht gefällt, könnten Sie sie als object deklarieren und ToString aufrufen, um sie dann wie folgt aufzurufen:

var myVariable = ParseNDecimal(xml.Element("myElement").ValueOrDefault(0m));

Allerdings fühlt sich das für mich ein wenig falsch an. Es geht davon aus, dass das Parsen das Gegenteil des ToString-Formats sein wird.

Ursprüngliche Antwort

Es gibt nichts Besonderes in der Sprache, um Ihnen zu helfen. (Ich bin mir nicht sicher, ob Sie den genauen Code richtig haben - meinen Sie nicht etwas mit einem XAttribute?) Ich würde vorschlagen, eine Hilfsmethode zu schreiben:

var myVariable = xml.Element("myElement").ValueOrDefault(0m);

...

public static decimal ValueOrDefault(this XElement element, 
                                     decimal defaultValue)
{
    return element != null ?(decimal) element.Value : defaultValue;
}

Wenn Sie den Code in der Frage anpassen, werde ich das Gleiche für den Code hier tun. Ich vermute, Sie haben tatsächlich XAttribute verwenden wollen, was zu einem Problem mit Generics führt - ich habe das obige nicht auf generische Weise geschrieben, weil ich glaube, dass Sie den "Umwandlungsoperator in Decimal" des XAttribute anrufen wollen. Ein generischer Cast wird das nicht tun, da er zur Kompilierzeit nicht weiß, welche Art von Umwandlung Sie möchten. Sie können jedoch die obige Methode für alle Ergebnistypen überladen, die Sie interessieren.

1voto

Bevan Punkte 42255

Sie können den ?? Operator verwenden, um dies etwas sauberer zu schreiben, aber ich bin mir nicht sicher, ob Sie das tun sollten ...

Element() gibt null zurück, wenn kein Kind-Element mit diesem Namen vorhanden ist, daher könnten Sie hier ?? verwenden, um ein Standard-Element einzufügen. Sie müssen dies vor dem Aufruf des (decimal) Casts tun:

var myVariable 
    = (decimal)(xml.Element("myElement") ?? new XElement("myElement", 0));

Wie gesagt, auch wenn dies funktioniert, bin ich mir nicht sicher, ob Sie dies tun sollten. Das kann variieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X