C # ?? в сочетании с?: вопрос - PullRequest
3 голосов
/ 09 февраля 2009

Я создаю десериализатор XML для проекта и довольно часто сталкиваюсь с таким типом кода:

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

Есть ли лучший способ написать это утверждение?

РЕДАКТИРОВАТЬ: Возможно, я должен был уточнить мой пример, так как у меня есть вспомогательный метод для анализа строки в десятичную.

Ответы [ 3 ]

6 голосов
/ 09 февраля 2009

Вы можете использовать метод расширения:

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

EDIT:

«Универсальное» решение:

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

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

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

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

        return defaultValue;
    }
}
5 голосов
/ 09 февраля 2009

Редактировать: Учитывая отредактированный вопрос, это намного проще.

Снова используется метод расширения, но теперь нет необходимости выполнять преобразование в методе.

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

...

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

Если вам не нравится метод, принимающий строковый параметр, вы можете сделать так, чтобы он принимал object и вызывал ToString, а затем вызывал бы его так:

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

Однако, мне кажется, это немного неправильно. Предполагается, что синтаксический анализ будет обратным форматированию ToString.

Оригинальный ответ

Нет ничего особенно в языке, чтобы помочь вам. (Я не уверен, что вы правильно поняли код - разве вы не имеете в виду что-то с XAttribute?) Я бы предложил написать служебный метод:

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

...

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

Если вы измените код в вопросе, я сделаю то же самое для кода здесь. Я подозреваю, что вы действительно намеревались использовать XAttribute, что приводит к проблеме с генериками - я не написал вышеприведенное обобщенно, потому что я полагаю, что вы захотите вызвать XAttribute преобразование в десятичный "оператор. Обычное приведение не сделает этого, так как не знает, какое преобразование вы хотите во время компиляции. Однако вы можете перегрузить вышеуказанный метод для всех интересующих вас типов результатов.

1 голос
/ 09 февраля 2009

Вы можете использовать ?? оператор, чтобы написать это немного более аккуратно, но я не уверен, что вы должны ...

Element() возвращает значение null, если нет дочернего элемента с таким именем, так что вы могли бы использовать ?? скользить в элементе по умолчанию. Вы должны сделать это до вызова (decimal) cast:

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

Как я уже сказал, хотя это будет работать, я не уверен, что вы должны сделать это. YMMV.

...