зачем разрешать методы расширения для нулевых объектов?

какой смысл разрешать вызов методов расширения для нулевых объектов? это заставляет меня без необходимости проверять нулевой объект в методе расширения. AFAIK, я не могу понять это? Пожалуйста, объясни.


person Srinivas Reddy Thatiparthy    schedule 28.03.2011    source источник
comment
возможный дубликат нулевой цели метода расширения   -  person BrokenGlass    schedule 28.03.2011
comment
Возможно, плохой пример, но я видел: Image img = ((Image)null).FromBytes(File.ReadAllBytes(file)) вместо статического вспомогательного класса ImageUtility.   -  person BrunoLM    schedule 28.03.2011
comment
Отличительным преимуществом является возможность добавления хороших методов расширения, которые учитывают значения NULL лучше, чем их аналоги методов экземпляра. Отличным примером этого является SubString(). Если вы вызовете это для нулевой ссылки, это, конечно, вызовет исключение. Однако, если вы добавите метод расширения SubStringSafe(), проверяющий значение null, вы сможете избавиться от множества повторяющихся кодов, проверяющих значение null.   -  person RQDQ    schedule 28.03.2011
comment
Добавление к примеру @RQDQ: я использую простой метод расширения IsNullOrEmpty, использование которого кажется более естественным: myStringVar.IsNullOrEmpty().   -  person Daniel Hilgarth    schedule 28.03.2011
comment
@all, я не понимаю, почему люди голосуют за close?   -  person Srinivas Reddy Thatiparthy    schedule 28.03.2011


Ответы (7)


Методы расширения — это синтаксический сахар языка C#, они компилируются в обычные вызовы статических методов в ILCode. Статический метод ничего не знает о параметрах во время компиляции.

person Femaref    schedule 28.03.2011

Проще говоря, почему бы и нет?

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

По сути, вы просите, чтобы код был другим, чтобы:

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

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

if(arg == null)throw new ArgumentNullException();
person Jon Hanna    schedule 28.03.2011
comment
Я использую ArgumentNullException, так как в ILCode нет такого понятия, как метод расширения. Методы расширения — это просто статические методы, поэтому ArgumentNullException более подходит. - person Femaref; 28.03.2011
comment
@Femaref, я обычно тоже, но ничего ясного не вижу. В последнее время я склоняюсь к NullReference, потому что при отладке разработчик, скорее всего, будет смотреть на C# с вызовом в стиле метода, чем на использование метода в IL или статическом стиле. Интересно, есть ли что-нибудь официальное в руководствах по кодированию MS. - person Jon Hanna; 28.03.2011
comment
Ну, весь стек LINQ использует ArgumentNullException. - person Femaref; 28.03.2011
comment
@Femaref Думаю, я останусь таким, какой я есть, и отредактирую ответ соответствующим образом. Также не думайте, что я буду беспокоиться о том, чтобы пропустить NullReferenceException. - person Jon Hanna; 28.03.2011
comment
Если ему не нужна нулевая проверка, не реализуйте его как метод расширения. Следуйте соглашениям .NET Framework и принципу наименьшего удивления. - person Den; 26.09.2013
comment
@Den со стороны можно не удивляться. - person Jon Hanna; 26.09.2013
comment
@Femaref с тех пор, как я это написал, я передумал. Теперь я всегда выбрасывал ArgumentNullException во многом на том основании, о котором вы и Ден спорили (если, конечно, я не мог просто сделать что-то значимое с null). - person Jon Hanna; 28.07.2015

Методы расширения — это просто синтаксический сахар. На самом деле это статические методы другого класса, поэтому, поскольку вы можете написать

IEnumerable<int> foo = null;
Enumerable.Count(foo);

Вы также можете написать

IEnumerable<int> foo = null;
foo.Count();
person Jon    schedule 28.03.2011
comment
Вы можете написать это :D Но оба примера кода выдадут ArgumentNullException. Count не позволяет параметру source быть нулевым: msdn.microsoft.com/en-us/library/vstudio/bb338038.aspx - person Yves M.; 03.10.2013
comment
Затем напишите свой собственный, который сначала проверяет значение null и либо выдает, либо возвращает Count()... - person nurchi; 17.09.2014

Иногда разрешение вызова метода расширения для нулевого объекта упрощает ваш код, позволяя переместить проверку нулевого значения в метод, а не в место вызова. Например, у вас может быть метод расширения, который возвращает List<T>, но при вызове для нулевого объекта возвращает пустой List<T>.

person Kevin Carroll    schedule 16.01.2012

  1. Методы расширения преобразуются в вызовы статических методов, поэтому код все равно должен будет проверять аргументы null, поскольку нет никакого способа избежать нормального вызова статического метода без синтаксического сахара метода расширения.
  2. Добавление чего-то вроде проверки, за которой следует NullArgumentException, может потребовать времени выполнения, и пользователь может вместо этого захотеть утвердить или использовать что-то еще.
  3. Замену будет сложнее объяснить или сделать автоматически, поскольку простая замена метода расширения соответствующим вызовом статического метода изменит поведение кода.
  4. Есть законный случай, когда вы хотите разрешить нулевые аргументы (например, преобразования из объектной модели в другую, когда нулевой объект одного типа преобразуется в нулевой объект второго типа)
person Julien Roncaglia    schedule 28.03.2011

Методы расширения — это просто статические методы:

List<int> x = null;
x.Count()

Эквивалентно:

List<int> x = null;
System.Linq.EnumerableExtensions.Count(x); 
//EnumerableExtensions may not be the class, but you get the idea
person Tejs    schedule 28.03.2011

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

public static bool IsNullOrEmpty(this string value)
{
    return string.IsNullOrEmpty(value);
}

Таким образом, вы можете использовать

string s = null;
if (s.IsNullOrEmpty()) // no null reference error!
    ...

Вместо

string s = null;
if (string.IsNullOrEmpty(s))
    ....
person Bigjim    schedule 15.06.2015