Оператор безопасной навигации в 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


Однако это работает только в некоторых случаях. случаи.

503   4  
c#

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# версии 6 (развернуто в Visual Studio 2015).

Оставшаяся часть моего ответа была написана для более ранних версий языка C#, которые не имели оператора ?..
Вообще говоря, если вы находитесь в ситуации, когда вы обращаетесь к глубоко "вложенному" свойству, такому как 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, Не забудьте проверить, является ли person null, прежде чем обращаться к его свойству 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

    Ничего не найдено.