Лучший способ обработать NULL - PullRequest
18 голосов
/ 28 сентября 2010

В верхней части моих функций я пытаюсь наилучшим образом обработать нуль, входящий в мои процедуры в C #. Какой лучший способ проверки и обработки нулевого значения и почему? Я добавил полный код того, что я использую прямо сейчас, и Решарпер говорит мне использовать Вариант № 1. Обычно я делаю то, что говорится, потому что понимаю, почему это делает его более эффективным. На этот раз я не уверен, поэтому должен спросить.

Option #1
if (sender == null) return;

// Code goes here

or

Option #2
if (sender != null)
{ 
     // Code goes here
}

Complete Code
        private void EmployeeMouseHoverToolTip(object sender, EventArgs e)
        {
            if (sender != null)
            {
                var sUserIdentifier = ((C1TextBox)sender).Text;
                var userIdentifier = Guid.Empty;
                if (Utilities.IsGuid(sUserIdentifier))
                {
                    userIdentifier = new Guid(sUserIdentifier);
                }

                var toolTipText = Utilities.UserIdentifierToName(userIdentifier);
                c1SuperTooltip.SetToolTip(sender as C1TextBox, toolTipText);
            }
        }

Ответы [ 18 ]

43 голосов
/ 28 сентября 2010

Лучший код - запретить null (вместо того, что вы делаете). Это не всегда возможно (иногда важно обрабатывать null осмысленно), но в большинстве случаев это так.

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

if (arg == null)
    throw new ArgumentNullException("arg");

Многие (если не большинство) методов в .NET Framework и в хороших библиотеках делают это таким образом.

Кроме того, sender события не должно никогда быть null, и я бы сказал, что проверка его избыточна. Если на это событие будет передано null, то с вашим кодом что-то серьезно не так.

То, как вы обрабатываете null (молча глотая его и ничего не делая), может маскировать серьезные ошибки в приложении и редко, если вообще когда-либо, подходит. Ошибки в коде должны вызывать подозрительное поведение, а не быть скрытыми.

11 голосов
/ 28 сентября 2010

Почему бы просто не сделать вид, что нулевая ссылка никогда не возникает, и не перехватить исключение NullPointerException?

Вы получаете трассировку стека, много информации, и она обрабатывается как исключение.

9 голосов
/ 28 сентября 2010

Вариант 1, по моему мнению, предложен resharper, потому что он облегчает чтение кода. В итоге вы получите:

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

Что касается производительности, то, вероятно, разница невелика (хотя, если это имеет значение для вас, измерьте ее ). Нет ничего, что могло бы помешать JIT-компилятору переписывать одну форму в другую в любом случае, если они все равно не получили вывод в виде идентичного MSIL от C # -компилятора.

7 голосов
/ 28 сентября 2010

Это обработчик событий, он должен вызываться только элементами управления в ответ на событие (никогда напрямую не вашим собственным кодом), поэтому вам не нужно беспокоиться о проверках на ноль или даже проверках типа для параметра sender (если вы только прикрепите этот обработчик события к тому же типу элемента управления).Я бы сделал это просто так:

private void EmployeeMouseHoverToolTip(object sender, EventArgs e) {  
  var txtBox = (C1TextBox)sender;
  var sUserIdentifier = txtBox.Text;
  var userIdentifier = Utilities.IsGuid(sUserIdentifier) ? 
    new Guid(sUserIdentifier) : 
    Guid.Empty;
  var toolTipText = Utilities.UserIdentifierToName(userIdentifier);
  c1SuperTooltip.SetToolTip(txtBox, toolTipText);
}

На самом деле, я бы пошел еще дальше и отделил логику, чтобы получить текст подсказки из логики для чтения и обновления пользовательского интерфейса.Примерно так:

private void EmployeeMouseHoverToolTip(object sender, EventArgs e) {  
  var txtBox = (C1TextBox)sender;
  var toolTipText = ResolveUpdatedTooltipText(txtBox.Text);
  c1SuperTooltip.SetToolTip(txtBox, toolTipText);
}

private string ResolveUpdatedTooltipText(string sUserIdentifier) {
  var userIdentifier = ResolveGuid(sUserIdentifier);
  return Utilities.UserIdentifierToName(userIdentifier);
}

private Guid ResolveGuid(string sUserIdentifier) {
  return Utilities.IsGuid(sUserIdentifier) ? 
    new Guid(sUserIdentifier) : 
    Guid.Empty;
}

Поэтому вам не следует использовать какие-либо из предоставленных вами опций.

5 голосов
/ 28 сентября 2010

Не проверяйте это.

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

3 голосов
/ 28 сентября 2010

Я лично предпочитаю первый вариант

if (sender == null) return;

Он сокращает вложенность и повышает читабельность.

1 голос
/ 28 сентября 2010

Resharper нравится опция 1, так как это проверка предварительных условий.Когда предварительные условия не выполняются, выполняется ранний возврат.

Обычно ранний возврат разрушителен для читабельности кода, но в этом случае он очень читабелен.

Таким образом, вы можете легко добавить дополнительные проверки предварительных условий, такие как проверка содержимого EventArgs e, без необходимости переделки кода основной функции.

1 голос
/ 28 сентября 2010

Я предпочитаю

if (sender == null) return;

, с ним меньше вложенных операций в коде и ранний выход при нулевом.

1 голос
/ 28 сентября 2010

Я обычно хожу с вариантом № 1.Я чувствую, что это чище, и это значит более ясно.Кто бы ни читал код, он знает, что если мы благополучно прошли проверку на нулевое значение и завершили работу, то у нас не будет шансов возиться с нулевым значением в отправителе позже.

0 голосов
/ 01 июля 2014

вы можете использовать DBNull Class при назначении значения объекту ...

UserName = DBNull.Value != reader["UserName"] ? reader["UserName"].ToString() : default(string);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...