Оператор безопасной навигации в C#? [дубликат]
Возможный дубликат:
ярлык для "null if object is null, или object.член, если объект не равен null "
Некоторые языки имеют безопасный навигационный оператор, который позволяет не беспокоиться об исключениях нулевой ссылки.
Пример языка Groovy:
String lname = person.Name.ToLowerCase(); //throws exception if Name is null
String lname = person.Name?.ToLowerCase();//lname will be null if Name was null
Как я могу сделать нечто подобное в C#? Мое решение до сих пор - это метод расширения, подобный этому:
public static T o<T>(this T obj) where T : new()
{
return obj != null ? obj : new T();
}
//used like: String lname = person.o().Name; //returns null if person was null
Однако это работает только в некоторых случаях. случаи.
4 ответов:
Для таких случаев я обычно использую метод расширения
IfNotNull:Более сложным является введение понятия "может быть". Пример был приведен Дериком Бейли здесь.public static OUT IfNotNull<IN, OUT>(this IN v, Func<IN, OUT> f) where IN : class where OUT : class { return v == null ? null : f(v); }Обновление:
По состоянию на C# 6 теперь существует нуль-распространяющий оператор, который синтаксически выглядит точно так же, как заводной.
Вы ищете короткое замыкание оператор доступа к нулевому условному члену
Оставшаяся часть моего ответа была написана для более ранних версий языка C#, которые не имели оператора?.это было введено в язык C# версии 6 (развернуто в Visual Studio 2015).?..
Вообще говоря, если вы находитесь в ситуации, когда вы обращаетесь к глубоко "вложенному" свойству, такому какoutermostObject.a.b.c.X, вам, вероятно, следует рассмотреть перепроектирование вашего кода, поскольку такой доступ может указывать на то, что вы нарушаете установленные принципы ОО (такие как принцип наименьшего знания, он же закон Деметры).Некоторые другие варианты:
Во-первых , анти-внушение - не делайте этого:
string lname = null; try { lname = Person.Name.ToLower(); } catch (NullReferenceException ex) { } // inefficient and uglyВо-вторых , используя что - то вроде
Maybeмонады-вы можете определить такой тип самостоятельно. Это в основномNullable<T>, который реализуетIEnumerable<T>таким образом, что он возвращает пустую последовательность, когда значение не задано, или последовательность ровно одного элемента, если задано значение. Затем вы бы использовали его следующим образом:Maybe<string> personName = person.Name; var lname = (from name in personName select name.ToLower()).FirstOrDefault();Третье , и, вероятно, самое простое и практичное решение, предложенное Ульрихом:
var lname = person.Name != null ? person.Name.ToLower() : null;
P.S. , поскольку мы уже затронули тему проверки
null, Не забудьте проверить, является лиpersonnull, прежде чем обращаться к его свойствуName... ;- )
Я не знаю, как вернуть null из чего-то, что гарантированно не будет null, но для гарантии ссылки на объект можно использовать оператор null Coalescing
??Что-то вроде:
string lname = (person.Name??String.Empty).ToLower();Он вернет пустую строку вместо null в случае null, но он будет работать.
Возвращать пустую строку имеет больше смысла, чем возвращать null; если вы возвращаете null,то он снова бросит, если вы свяжете другой оператор с ним.
Сегодня не существует в C#, но вы можете написать его с помощью
SelectMany.String lname = from _ in person.Name from s in _.ToUpper() select s;Или
String lname = person.Name.SelectMany(_ => _.ToUpper(), s => s);(это было предложение Барта де смета вего выступлении PDC 2010 о будущем LINQ . Смотрите слайд №6.)
Comments