Почему обнуляемые явные операторы LINQ приведения бросают недопустимые исключения формата в пустые значения? - PullRequest
6 голосов
/ 28 января 2011

Прежде всего, я знаю, что на этот вопрос можно ответить простым ответом, что пустая строка не является нулевым значением. Кроме того, я только недавно обнаружил операторы приведения в начале года с помощью другого вопроса stackoverflow, и у меня нет большого опыта работы с ними. Тем не менее, причина, по которой все не так просто, заключается в том, что эти операторы приведения в сочетании с оператором объединения нулей выставляются как элегантное решение для устранения ошибок, таких как отсутствующие элементы или атрибуты в выражениях LINQ. Я начал использовать подход, описанный Скоттом в «Улучшение запаха кода LINQ ...» и ScottGu «Нулевой оператор объединения (и использование его с LINQ)» в качестве способа защиты против недействительных / пропущенных данных в сжатой и полус элегантной манере. Насколько я могу судить, это, кажется, одна из причин, по которой все перегрузки приведения в классы LINQ ставятся на первое место.

Итак, на мой взгляд, сценарий использования обращения с отсутствующим значением не сильно отличается от случая использования пустого значения, и в связанных статьях этот подход считается хорошим способом решения таких ситуаций. .

Сценарий:

int length = (int?)elem.Attribute("Length") ?? 0;

Если атрибут @Length отсутствует, приведение приводит к нулевому значению и ?? оператор возвращает 0;

Если атрибут @Length существует, но он пуст, внутреннее преобразование преобразуется в int.tryparse и выдает исключение формата. Конечно, для моего использования я хотел бы, чтобы он не возвращался и просто возвращал бы нуль, чтобы я мог продолжать использовать этот подход в своем уже несколько запутанном коде LINQ.

В конечном счете, не столько я не могу придумать решение, но еще больше, чтобы мне было интересно услышать, есть ли очевидный подход, который я пропустил, или если у кого-то есть хорошая точка зрения о том, почему пропал Сценарий стоимости был рассмотрен, но сценарий пустого значения не был.

Редактировать

Кажется, есть несколько ключевых моментов, которые я должен попытаться выделить:

  • Связанные статьи принадлежат сотрудникам MS, которыми я восхищаюсь и обращаюсь за руководством. Эти статьи, кажется, предлагают (или, по крайней мере, привлекают внимание) улучшенный / альтернативный подход для работы с необязательными значениями

  • В моем случае необязательные значения иногда бывают в виде отсутствующих элементов или атрибутов, но также имеют форму пустых элементов или значений

  • Описанный подход работает как ожидалось для пропущенных значений, но не работает для пустых значений

  • Код, который следует описанному подходу, по-видимому, защищает от отсутствия дополнительных значений, но на самом деле является хрупким и ломается в конкретном случае. Меня беспокоит появление защиты, когда на самом деле вы все еще в опасности

  • Это можно подчеркнуть, заявив, что оба связанных примера завершаются неудачно с исключением времени выполнения, если целевой элемент существует, но пуст

  • Наконец, кажется, что ключевым моментом является то, что описанный подход прекрасно работает, когда у вас есть контракт (возможно, через схему), который гарантирует, что элемент или атрибут никогда не будут 1053 * пустыми, но в случаях там, где этот контракт не существует, этот подход недействителен и требуется альтернатива

Ответы [ 2 ]

3 голосов
/ 28 января 2011

Я бываю согласен с поведением;если у меня нет атрибута / элемента "id", то я с радостью считаю это как ноль, но если он существует , но не анализирует , это другое- и пустая строка работает для очень немногих типов.Вам нужно будет сделать это вручную, или вы можете добавить метод расширения для XAttribute и т. Д .:

public static int? ParseInt32(this XAttribute attrib) {
    if(attrib != null && string.IsNullOrEmpty(attrib.Value)) return null;
    return (int?)attrib;
}

Примечание. Я использую приведение внутри как , в то время как это просто для int, .Parse был бы плохим примером для DateTime и т. Д., Который использует другой формат в xml, который приведен внутри преобразования.

1 голос
/ 28 января 2011

Что касается обходного пути, я уже создал метод расширения ниже. Я не думал о подходе, описанном Марком, который исправляет проблему с обнуляемым int и все еще использует ?? оператор для указания по умолчанию. Очень креативно и позволяет X ?? Образец Y для продолжения использования.

Я думаю, в конце концов, я, вероятно, предпочитаю подход Марка, потому что он сохраняет непротиворечивую закономерность в моих операторах присваивания и не привносит синтаксическую путаницу, которую имел вызов TryParseInt, так как он выглядел слишком сильно, как будто вы анализировали -1 или любой другой тип по умолчанию / предоставлено запасное значение.

    elem.Attribute("ID").TryParseInt(-1)

    /// <summary>
    /// Parses an attribute to extract an In32 value and falls back to the defaultValue should parsing fail
    /// </summary>
    /// <param name="defaultValue">The value to use should Int32.TryParse fail</param>
    /// <returns>The parsed or default integer value</returns>
    public static int TryParseInt(this XAttribute attr, int defaultValue)
    {
        int result;
        if (!Int32.TryParse((string)attr, out result))
        {
            // When parsing fails, use the fallback value
            result = defaultValue;
        }

        return result;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...