2009-04-01 2 views
18

Где вы проверяете, является ли объект, который вы передаете методу, null или нет?Где проверить, является ли объект нулевым или нет?

Следует ли протестировать объект перед вызовом метода? или внутри метода, который использует аргумент?

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     // Check if person is null here? or within PrintAge? 

     PrintAge(new Person { Age = 1 }); 
    } 

    private static void PrintAge(Person person) 
    { 
     // check if person is null here? 

     Console.WriteLine("Age = {0}", person.Age); 
    } 
} 

public class Person 
{ 
    public int Age { get; set; } 
} 

Имея «нулевую» проверку в обоих классах, кажется, слишком избыточный код.

[РЕДАКТИРОВАТЬ]: Что было бы полезным для проверки нулевого значения в вызывающем или вызываемом абоненте?

[EDIT2]: Я просто столкнулся с Defensive Programming и, похоже, защищает проверку нулевого номера в пределах вызываемого абонента. Интересно, является ли это общепринятой практикой.

+0

Вы можете проверить эту ссылку для прямой вперед анализа [1] [1 ]: http://stackoverflow.com/questions/2537987/how-to-check-if-an-object-is-defined – CeganB

ответ

3

Вы можете создать метод для работы только с действительными объектами.

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

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

Так что, если ваш метод не знаю точно, как обрабатывать недействительный объект и метод не будет следовать за дополнительную логику в недопустимой случае вы должны поставить

Debug.Assert(Person); 

в PrintAge начинаются и это будет заставляет вас делать проверки верхний стек вызовов.

Нижняя функция в иерархии - это меньше проверок, которые она должна выполнить. Ниже приведены недостатки выполнения проверок в функциях, выполняющих работу.

  • Функция, которая делает фактическую работу должен быть как можно более четкими без массы если s
  • Функция будет называться более чем много раз
  • Такая функция может вызывать такие функции, и они может снова вызвать такие функции. Каждая из них будет выполнять ту же проверку
+2

Проблема с Debug.Assert заключается в том, что если вы явно не включите символ DEBUG в свою сборку релизов, ваш код будет вести себя по-разному в разработке и в производстве - это нехорошо.Производство - это время, когда вы хотите * на самом деле * убедиться, что вы не продолжаете работать с плохими данными :) –

+0

Assert in Debug заставит вас делать проверки перед вызовом этого PrintAge –

+0

+ Отмечено как ответ: «Каждый из них будет выполнять та же проверка » – Sung

2

Вы имеете в виду проверку обоих методов? Я бы проверял в PrintAge точно, и если это имеет смысл и в Main. Я не думаю, что есть определенный ответ в целом. Это зависит от :-)

4

Я бы сказал, что проверка его n PrintAge, казалось, имела больше смысла, поскольку это выполняет контракт на рутину. Разумеется, вы могли бы заменить нулевые проверки кодом Debug.Assert() для проверки во время тестирования, но не во время выпуска.

1

Что бы вы хотели сделать, если экземпляр null?

Я думаю, что это зависит от API, который вы предоставляете &. Определите контракт (как это делают классы .net framework). Сказав это, вам не нужно проверять значение null (в основном), если метод определяет ожидаемый результат в случае передачи нулевой ссылки на него.

+0

На самом деле это зависит от многих случаев, что я должен делать, когда объект имеет значение null. Если я проверю на null в вызываемом, то я бы бросил исключение или ничего не сделал. В рамках вызываемой функции я бы сделал то же самое. – Sung

+0

Что я имею в виду - позволяет предположить, что это метод, который вы позволяете внешним пользователям вызывать, что бы вы хотели сделать в вызываемом методе, если переданное значение равно null? – shahkalpesh

+0

@shahkalpesh: Иногда я хотел бы выбросить исключение или просто вернуть пустой список в зависимости от того, что делает метод (будь то метод Get/Set). – Sung

2

Обычно я допускаю, чтобы мои проверки не соответствовали моим ожиданиям; если я ожидаю, что что-то будет нулевым или я не уверен в этом, добавлю чек. В противном случае я этого не делаю. Исключения Nulllpointer являются одними из самых простых проблем для отслеживания, поэтому чрезмерное разбрызгивание кода чеков. В конкретном примере я ничего не проверю, потому что это интуитивно, это не null.

+0

Итак, в основном, ваша практика такова, что она зависит от текущей ситуации? – Sung

+0

Да. Я пытаюсь выразить свои ожидания, даже через такие проверки. – krosenvold

0

Резервный код не самый изящный, но его сейф.

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

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

1

Существует только один случай, когда конструктор может вернуть null [new() на Nullable<T>] - поэтому код вызова не нужно проверять.

Вероятность освобождения от ответственности должно быть check; бросая ArgumentNullException, если это было null. В .NET 4.0 это будет лучше обслуживаться кодовыми контрактами. Но еще нет; -p

+0

У меня все еще возникает проблема с пониманием: «почему» код вызова не нужно проверять и сбрасывать нулевую проверку у вызываемого. – Sung

+0

Потому что он не может (с исходным кодом) быть нулевым. –

6

У вас нет ничего, чтобы проверить в Main - вы используете оператор new, который никогда не возвращает нуль (кроме Nullable<T>).

Было бы вполне разумно проверить в PrintAge, особенно если оно было опубликовано.(Для частных API, это менее важно сделать проверку аргументов, но он все еще может быть очень полезным.)

if (person == null) 
{ 
    throw new ArgumentNullException("person"); 
} 

В эти дни в C# 3.0 я обычно use an extension method for this.

0

Определенно зарегистрируйтесь в PrintAge, это подходящее место для проверки. Он может быть избыточным, но никого не повредит, если вы его не выполняете 1000 раз в секунду. (В зависимости от проверки выкиньте исключение или исправьте его, если сможете)

Другая проверка зависит от вашего фактического потока, в этом примере у вас нет потока, поэтому я не могу прокомментировать этот бит. Но обычно рассматривайте свои параметры как испорченные.

+0

Почему проверка на недопустимость в «PrintAge» была бы «правильным местом для проверки»? Первоначально я беспокоился о том, что избыточный код повсюду ... – Sung

+0

Я думаю, что это было бы правильно, потому что если вы выберете PrintAge из другого места, он все равно будет функционировать правильно (или, по крайней мере, лучше). –

+0

Но, очевидно, это может привести к избыточности, когда у вас есть несколько аналогичных функций PrintAge, и это не слишком много для этого. –

8

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

    -------------------------- 
        |       | 
        |   Library   | 
        |       | 
-------  ---------  ---------- | 
|  |  |   |  |   | | 
| Outer |  | Library |  | Library | | 
|  | ===> | Entry | ===> | Backend/ | | 
| World |  | Method |  | Helpers | | 
|  |  |   |  |   | | 
-------  ---------  ---------- | 
        |       | 
        |       | 
        -------------------------- 

Если вы приняли переданные данные в методе ввода, вы должны выполнить требуемое действие и вернуть exspected результата, то есть обрабатывать все остальные случаи.

UPDATE

Чтобы clearify ситуацию внутри библиотеки. Там могут быть нулевые проверки, но только из-за логики, а не из-за проверки параметров. Есть две возможности для размещения нулевых проверок внутри библиотеки. Первый, если вызываемый метод знает, как обрабатывать нулевые значения.

private CallingMethod() 
{ 
    CalledMethod(someData); 
} 

private CalledMethod(Object parameter) 
{ 
    if (parameter == null) 
    { 
     // Do something 
    } 
    else 
    { 
     // Do something else 
    } 
} 

И вторая ситуация, если вы вызываете метод, который не может обрабатывать нулевые значения.

private CallingMethod() 
{ 
    if (someData == null) 
    { 
     // Do the work myself or call another method 
    } 
    else 
    { 
     CalledMethod(someData); 
    } 
} 

private CalledMethod(Object parameter) 
{ 
    // Do something 
} 

Вся идея заключается в том, чтобы отказаться от дел, вы не можете обрабатывать immideatly и обрабатывать все остальных случаях правильно. Если вход недействителен, вы генерируете исключение. Это заставляет вызывающего абонента предоставлять только допустимые значения и не позволяет вызывающему абоненту продолжать выполнение с бессмысленными возвращаемыми значениями (кроме того, что вызывающий объект помещает исключение, а продолжает).

+0

Итак, в «Библиотечном бэкэнд/помощнике» нет «нулевой» проверки как для вызывающего, так и для вызываемого абонента? Правильно ли я понимаю вашу точку зрения? – Sung

+0

Там могут быть нулевые проверки, но только если это требуется по фактической логике. Для проверки параметров нет нулевых проверок. –

0

PrintAge должен быть методом для Person, а не статическим, принимающим параметр Person как. Никакой проверки не требуется.

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

+0

«Проверка нулевых значений делает код излишне сложным» <- внутри вызывающего или вызываемого абонента? – Sung

+0

Оба места. Мое предпочтение состоит в том, чтобы покончить с необходимостью проверить вообще. – Morendil

1

Как я понимаю, ваш вопрос более общий, чем иллюстрированный вашим примером. Мои предпочтения заключаются в следующем:

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

Брэд Абрамс имеет еще некоторый вход здесь: [? Как проверить, если объект определен] http://blogs.msdn.com/brada/archive/2004/07/11/180315.aspx

+0

@Brian: Да, мой вопрос был слишком общим. – Sung

 Смежные вопросы

  • Нет связанных вопросов^_^