Operator ??, that was introduced in the .NET 2.0, takes first place in my top used C# idioms list a long time, but unfortunately it is rarely used in projects I’ve participated. Therefore these snippets could be found in production code very often:
1 2 3 4 5 | public string Caption { get { return ViewState["Caption"] != null ? (string) ViewState["Caption"] : ""; } set { ViewState["Caption"] = value; } } |
Or even:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public string VisibleStatistic { get { string retval = (string) ViewState["VisibleStatistic"]; return retval == null ? "" : retval; } set { ViewState["VisibleStatistic"] = value; } } public string SelectedCategoryName { get { object retval = ViewState["SelectedCategoryName"]; if (retval != null) return (string) retval; return String.Empty; } set { ViewState["SelectedCategoryName"] = value; } } |
Almost 50% of this could be easily removed, and you will get beautiful and clear code, just right after you will understand what the hell is operator ??. Here is information from MSDN:
The ?? operator returns the left-hand operand if it is not null, or else it returns the right operand.
Easy and clean explanation. Let’s try to rewrite all these examples using this operator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public string Caption { get { return (string) ViewState["Caption"] ?? String.Empty; } set { ViewState["Caption"] = value; } } public string VisibleStatistic { get { return (string) ViewState["VisibleStatistic"] ?? String.Empty; } set { ViewState["VisibleStatistic"] = value; } } public string SelectedCategoryName { get { return (string) ViewState["SelectedCategoryName"] ?? String.Empty; } set { ViewState["SelectedCategoryName"] = value; } } |
In case of value-types this approach will not work: you will get NullReferenceException. But do not worry — in this case we can use Nullable-types. Before:
1 2 3 4 5 | public int FirstWidth { get { return ViewState["FirstWidth"] != null ? (int) ViewState["FirstWidth"] : 0; } set { ViewState["FirstWidth"] = value; } } |
After:
1 2 3 4 5 | public int FirstWidth { get { return (int?) ViewState["FirstWidth"] ?? 0; } set { ViewState["FirstWidth"] = value; } } |
When you are using ?? operator, expression will be evaluated in the left to right order, so you can use something like this:
1 | string name = FirstName ?? LastName ?? "Anonymous"; |
Of course, it looks more readably than the:
1 2 3 4 5 6 7 | string name; if (FirstName != null) name = FirstName; else if (LastName != null) name = LastName; else name = "Anonymous"; |
And a fortiori than:
1 2 3 | string name = FirstName != null ? FirstName : (LastName != null ? LastName : "Anonymous"); |
Add it to your armoury!
Отлично! Спасибо, буду знать. Очень удобно. Особенно строить цепи типа:
PS. В форме комментариев два флажка уведомления по мылу. Поставил оба, для верности:)
Действительно полезный оператор.
В Groovy (увы с .NET я не дружен) он называется “Elvis operator” и обозначается “смайлом” ?:
В JavaScript сделано проще:
ruby way:
2lusever: не совсем правильно. Вот в этом случае JavaScript ведет себя не так, как C# и ruby:
2
3
// Тут будет "Anonymous", а в C# и ruby - ""
var name = firstName || middleName || lastName || "Anonymous";
2 lusever
даже не смотря на то, что в JS сделано не совсем то, не ясно в чём “проще”?
‘||’ писать проще чем ‘??’, что-ли? :) анекдот прямо:
– ‘||’ проще чем ‘??’!
– чем проще-то?
– чем ‘??’!
Откровенно говоря восхищаться тут нечем
Очевидно, что начальное значение переменной просто неправильно проинициализировано null и это обязательно выплывет где-нибудь в другом не столь очевидном месте.
Непонятно, чем это лучше
PS
Прослеживая историю развития С# легко убедиться, что он семимильными шагами движется в сторону Perl, где подобные быстрые операторы уже сыграли злую шутку – зачастую пишутся программы понятные только создателю, да и то не всегда.
Отчего же не восхищаться, если простой и удобный синтаксис делает жизнь проще?
Итак, по порядку.
Насчет непроинициализированного значения переменной — тут Вы правы. Но если проинициализировать,– значение 0 попадет во ViewState, что означает увеличение размера страницы. А зачем это нужно, если переменная имеет значение по умолчанию?
2
return Array.Find({FirstName, LastName, "Anonimous"}, NotNull);
Непонятно, чем лучше? Тогда почему бы не писать
Ведь это то же самое.
Насчет Вашего P.S. Тут вообще мрак. Перл никогда не был функциональным языком, а именно в этом направлении движется C#.
C# куда движется?!? ты чего это? imo ты тут очень ошибаешься. напомню, что функциональный язык избегает состояний и изменяемых объектов.
ты может что-то другое хотел сказать?
Я что хотел сказать, то сказал. Считаю, что C# движется в сторону функциональщины (читай F# [читай Ocaml]).
ну это ж бред :)
F# такой себе мультипарадигмный язык. C# такой себе императивный ОО язык. движутся параллельными курсами и пересекаются только в IL :)
или ты предполагаешь в (не)далёком будущем смерть(забытие, поглощение) одного из упомянутых языков в пользу другого?
Нет, конечно, ничьей смерти я не жду :-) Просто как-то издавно повелось, что часть фич, успешно обкатанных на F#, портируют на C#.
А насчет функциональных возможностей – так, навскидку: 1.1 -> 2.0 (анонимные функции, замыкания) -> 3.5 (лямбда-выражения, анонимные типы [кстати, неизменяемые], linq). Я не говорю, что C# станет полностью функциональным (это, естественно, бред). И не говорю, что F# умрет (тем более его не так давно начали продвигать в массы). Я просто говорю, что C# идет ну никак не сторону Perl.
Простите, но Ваши представления о “функциональности” несколько некорректные о чем вам правильно заметил COTOHA. Лямбда выражения, анонимные функция, замыкания и прочая упомянутая ерунда не являются основными признаками функционального языка. Основное свойство функциональных языков – отсутствие переменных. Именно поэтому C# более Perl (в нем это все есть), нежели Lisp и уж тем более Haskel.
Более того он вообще не имеет определенной коцепции, что ярко доказываетя ??, using и прочим синтаксическим шумом.
Возможно ?? ддя отдельных маргиналов и полезен, хотя и путает код. Но почему тогда нет определения любого оператора, например !? или +!.
Using вообще-то говоря частный случай замыкания. Так почему же он сделан частью языка, а не частью стандартной библиотеки?
Хочу попросить автора замечательного блога написать свое IMHO по поводу кодо-генерирующий шаблонных фреймворков для .NET, типа CodeSmith, SmartCode, SQLNetFramework. Использует ли автор что-то подобное, если да, то что именно, какое мнение сложилось от других продуктов?
Уже самый популярный оператор среди тех кто кодит на .NET 2.0, очень удобно и просто применять. У меня он дааавно на вооружении)
Coalesce ?? operator in C# 2.0 | Dmytro Shteflyuk’s Home…
Появившийся в .NET 2.0 оператор ?? уверенно занимает в моем хит-параде наиболее часто используемых приемов первое место, но при этом довольно …
По долгу службы мне приходится перелопачивать горы кода на C# и Java. Честно говоря, такого рода операторы в больших количествах делают код малочитаемым. И я бы не рекомендовал им злоупотреблять, особенно в больших проектах.
Hi,i like this plugin.
And I used it in my site.
But I’m so gloomy,because when i use
it was transferred meaning like this
the realyy it seemed is
how can i do ?