В C#, что происходит, когда вы вызываете метод расширения на нулевом объекте?
метод вызывается с нулевым значением или он дает исключение нулевой ссылки?
MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?
Если это так, мне никогда не нужно будет проверять мой параметр "this" на null?
7 ответов:
Это будет работать нормально (без исключения). Методы расширения не используют виртуальные вызовы (т. е. он использует инструкцию "call" il, а не "callvirt"), поэтому нет нулевой проверки, если вы не напишете ее самостоятельно в методе расширения. Это действительно полезно в нескольких случаях:
public static bool IsNullOrEmpty(this string value) { return string.IsNullOrEmpty(value); } public static void ThrowIfNull<T>(this T obj, string parameterName) where T : class { if(obj == null) throw new ArgumentNullException(parameterName); }etc
По сути, вызовы статических вызовов очень буквальны-т. е.
string s = ... if(s.IsNullOrEmpty()) {...}будет:
string s = ... if(YourExtensionClass.IsNullOrEmpty(s)) {...}где, очевидно, нет нулевой проверки.
дополнение к правильному ответу от Marc Gravell.
вы можете получить предупреждение от компилятора, если очевидно, что этот аргумент равен null:
default(string).MyExtension();хорошо работает во время выполнения, но обеспечивает предупреждение
"Expression will always cause a System.NullReferenceException, because the default value of string is null".
как вы уже обнаружили, поскольку методы расширения-это просто прославленные статические методы, они будут вызываться с
nullссылки передаются безNullReferenceExceptionбыть брошенным. Но, поскольку они выглядят как методы экземпляра для вызывающего объекта, они также должны вести как таковой. Затем вы должны, большую часть времени, проверятьthisпараметр и бросить исключение, если этоnull. Это нормально не делать этого, если метод явно заботится оnullзначения и его название указывает на это должным образом, как в приведенных ниже примерах:public static class StringNullExtensions { public static bool IsNullOrEmpty(this string s) { return string.IsNullOrEmpty(s); } public static bool IsNullOrBlank(this string s) { return s == null || s.Trim().Length == 0; } }Я написал блоге об этом некоторое время назад.
в метод расширения будет передано значение null.
Если метод пытается получить доступ к объекту без проверки, это null, то да, он будет бросать исключение.
парень здесь написал" IsNull "и" IsNotNull " методы расширения, которые проверяют, является ли ссылка переданной null или нет. Лично я думаю, что это аберрация и не должен был видеть свет дня, но это совершенно правильный c#.
как указывали другие, вызов метода расширения по нулевой ссылке приводит к тому, что этот аргумент равен нулю, и ничего особенного не произойдет. Это дает повод к идее использовать методы расширения для написания защитных предложений.
вы можете прочитать эту статью для примера: Как уменьшить Цикломатическую сложность: Guard Clause этой
public static class StringExtensions { public static void AssertNonEmpty(this string value, string paramName) { if (string.IsNullOrEmpty(value)) throw new ArgumentException("Value must be a non-empty string.", paramName); } }Это метод расширения класса string, который может быть вызван на null ссылка:
((string)null).AssertNonEmpty("null");вызов работает нормально только потому, что среда выполнения успешно вызовет метод расширения по нулевой ссылке. Затем вы можете использовать этот метод расширения для реализации предложений guard без беспорядочного синтаксиса:
public IRegisteredUser RegisterUser(string userName, string referrerName) { userName.AssertNonEmpty("userName"); referrerName.AssertNonEmpty("referrerName"); ... }
extensionmethod является статическим, поэтому, если вы ничего не делаете с этим MyObject, это не должно быть проблемой, быстрый тест должен проверить это :)
есть несколько золотых правил, когда вы хотите, чтобы ваш был читаемым и вертикальным.
- стоит сказать, что Эйфель говорит, что конкретный код, инкапсулированный в метод, должен работать против некоторого ввода, что код работоспособен, если выполняются некоторые предварительные условия и обеспечивают ожидаемый результат
в вашем случае - DesignByContract нарушен ... вы собираетесь выполнить некоторую логику на нулевом экземпляре.
Comments