Насколько полезный C#?? оператор?

Я подозреваю в общем случае, это твердо; XML-схема допускает некоторые довольно причудливые конструкции типа. Я не уверен, как Вы сделали бы группы замены или расширения ограничений типов, например.

Однако должно быть возможно столкнуть что-то вполне быстро (особенно отображающийся от классов в Системе. Xml. Схема), который работает на 90% схем (т.е. последовательность и элементы выбора с несколькими простыми типами данных).

24
задан captncraig 6 November 2009 в 18:48
поделиться

13 ответов

Я согласен с вами, что ?? обычно используется ограниченно - полезно предоставить запасное значение, если что-то имеет значение NULL, но бесполезно для предотвращения исключения нулевой ссылки в случаях, когда вы хотите продолжить детализацию свойств или методов иногда- пустая ссылка.

ИМХО, а чего нужно намного больше ?? - это оператор "разыменования нуля", который позволяет вам объединять длинные цепочки свойств и / или методов вместе, например ab (). cd (). e , без необходимости проверять каждый промежуточный шаг на отсутствие значения NULL. В языке Groovy есть оператор безопасной навигации , и он очень удобен.

К счастью, похоже, что команда C # знает об этом пробеле в функциях. См. Предложение connect.microsoft.com для команды C # по добавлению оператора нулевого разыменования в язык C #.

Мы получаем довольно много запросов на функции, похожие на этот. Знак "?" версия, упомянутая в сообществе самое близкое нашему сердцу обсуждение - он позволяет вам проверять значение null на каждая "точка" и прекрасно сочетается с существующий ?? оператор:

a? .b? .c ?? d

Значение, если любой из a, ab или abc null используйте вместо этого d.

Мы рассматриваем это на будущее выпуск, но его не будет в C # 4.0.

Еще раз спасибо,

Mads Torgersen, C # Language PM

Если вам также нужна эта функция в C #, добавьте свои голоса к предложению на сайте подключения! : -)

Я использую один обходной путь, чтобы обойти отсутствие этой функции, - это метод расширения, подобный тому, который описан в этой записи блога , чтобы разрешить такой код:

string s = h.MetaData
            .NullSafe(meta => meta.GetExtendedName())
            .NullSafe(s => s.Trim().ToLower())

Этот код либо возвращает h.MetaData.GetExtendedName (). Trim (). ToLower () или возвращает значение null, если h, h.MetaData или h.MetaData.GetExtendedName () имеет значение null. Я также расширил это, чтобы проверять пустые или пустые строки, или пустые или пустые коллекции. Вот код, который я использую для определения этих методов расширения:

public static class NullSafeExtensions
{
    /// <summary>
    /// Tests for null objects without re-computing values or assigning temporary variables.  Similar to 
    /// Groovy's "safe-dereference" operator .? which returns null if the object is null, and de-references
    /// if the object is not null.
    /// </summary>
    /// <typeparam name="TResult">resulting type of the expression</typeparam>
    /// <typeparam name="TCheck">type of object to check for null</typeparam>
    /// <param name="check">value to check for null</param>
    /// <param name="valueIfNotNull">delegate to compute if check is not null</param>
    /// <returns>null if check is null, the delegate's results otherwise</returns>
    public static TResult NullSafe<TCheck, TResult>(this TCheck check, Func<TCheck, TResult> valueIfNotNull)
        where TResult : class
        where TCheck : class
    {
        return check == null ? null : valueIfNotNull(check);
    }

    /// <summary>
    /// Tests for null/empty strings without re-computing values or assigning temporary variables
    /// </summary>
    /// <typeparam name="TResult">resulting type of the expression</typeparam>
    /// <param name="check">value to check for null</param>
    /// <param name="valueIfNotNullOrEmpty">delegate to compute non-null value</param>
    /// <returns>null if check is null, the delegate's results otherwise</returns>
    public static TResult CheckNullOrEmpty<TResult>(this string check, Func<string, TResult> valueIfNotNullOrEmpty)
        where TResult : class
    {
        return string.IsNullOrEmpty(check) ? null : valueIfNotNullOrEmpty(check);
    }
    /// <summary>
    /// Tests for null/empty collections without re-computing values or assigning temporary variables
    /// </summary>
    /// <typeparam name="TResult">resulting type of the expression</typeparam>
    /// <typeparam name="TCheck">type of collection or array to check</typeparam>
    /// <param name="check">value to check for null</param>
    /// <param name="valueIfNotNullOrEmpty">delegate to compute non-null value</param>
    /// <returns>null if check is null, the delegate's results otherwise</returns>
    public static TResult CheckNullOrEmpty<TCheck, TResult>(this TCheck check, Func<TCheck, TResult> valueIfNotNullOrEmpty)
        where TCheck : ICollection
        where TResult : class
    {
        return (check == null || check.Count == 0) ? null : valueIfNotNullOrEmpty(check);
    }
}
27
ответ дан 28 November 2019 в 22:08
поделиться

?? [ Оператор 1140151] похож на метод coalesce в SQL, он возвращает вам первое ненулевое значение.

var result = value1 ?? value2 ?? value3 ?? value4 ?? defaultValue;
32
ответ дан 28 November 2019 в 22:08
поделиться

Я обычно использую его для строк или типов, допускающих значение NULL.

string s = someString ?? "Default message";

проще, чем

   string s;
   if(someString == null)
     s = "Default Message";         
   else
     s = someString;

или

  string s = someString != null ? someString : "Default Message";
22
ответ дан 28 November 2019 в 22:08
поделиться

Я часто использую его для ленивых экземпляров объектов в свойствах, например

public MyObject MyProperty
{
    get
    {
        return this.myField ?? (this.myField = new MyObject());
    }
}

Это использует тот факт, что в C # присваивание является выражением, поэтому вы можете назначать и использовать результат выражения (присвоенное значение) все в одном заявлении. Я все еще чувствую себя немного грязным по поводу этого шаблона кода, но он короче, чем альтернатива (ниже), так что он почти выигрывает.

public MyObject MyProperty
{
    get
    {
        if (this.myField == null)
        {
            this.myField = new MyObject();
        }

        return this.myField;
    }
}
11
ответ дан 28 November 2019 в 22:08
поделиться

?? фактически является оператором проверки на null.

Причина, по которой ваш код попадает в затруднительное положение, заключается в том, что если «someObject имеет значение null, то .someMember является свойством для нулевого объекта. Сначала вам нужно будет проверить someObject на значение null.

РЕДАКТИРОВАТЬ:

Я должен добавить, что да, я нахожу ?? очень полезным, особенно при обработке ввода в базу данных, особенно из LINQ, но также и в других случаях. Я часто его использую.

7
ответ дан 28 November 2019 в 22:08
поделиться

Как и в случае с FYI, тернарный оператор генерирует последовательность IL, отличную от нулевого оператора объединения. Первый выглядит примерно так:

// string s = null;
// string y = s != null ? s : "Default";
    ldloc.0
    brtrue.s notnull1
    ldstr "Default"
    br.s isnull1
    notnull1: ldloc.0
    isnull1: stloc.1

А второй выглядит примерно так:

// y = s ?? "Default";
    ldloc.0
    dup
    brtrue.s notnull2
    pop
    ldstr "Default"
    notnull2: stloc.1

Исходя из этого, я бы сказал, что нулевой оператор объединения оптимизирован для своей цели, а не просто синтаксический сахар.

8
ответ дан 28 November 2019 в 22:08
поделиться

Я использовал его с материалом App.Config

string somethingsweet = ConfigurationManager.AppSettings["somesetting"] ?? "sugar";
3
ответ дан 28 November 2019 в 22:08
поделиться

Часто кажется хорошей идеей заменить подробный синтаксис более компактной формой. Но обычно это заканчивается просто запутыванием кода, ничего не получая. Современные стандарты рекомендуют более длинные и описательные имена переменных и использование более подробных стилей макета, чтобы сделать код более читаемым и понятным. более удобен в обслуживании.

Если я собираюсь научить свой мозг быстро разбирать ??, мне нужно найти ситуацию, в которой он показывает явное преимущество - то, что нельзя сделать другим способом, или где-нибудь, что позволяет значительный объем набора.

И это где ?? падает для меня. Это так редко бывает полезно, и?: И if / else - такие быстрые и удобочитаемые альтернативы, что действительно не имеет смысла использовать другой синтаксис, который не дает ничего нового.

a = b ?? с ?? г ?? е; звучит здорово. Но мне никогда не приходилось это делать!

Что меня раздражает, так это то, что я хочу использовать ??, но каждый раз, когда я думаю: «Ох, может, я могу использовать ?? здесь», я понимаю, что не Я хочу использовать сам объект, но его член.

name = (user == null)? "лань": user.Surname;

И, к сожалению, ?? не

1
ответ дан 28 November 2019 в 22:08
поделиться

Я использую его при работе с методами, которые могут возвращать значение null при нормальной работе.

, например, допустим, что у меня есть класс контейнера, который имеет метод Get, который возвращает значение null, если контейнер не содержит ключа ( или, возможно, null - допустимая ассоциация). Тогда я мог бы сделать что-то вроде этого:

string GetStringRep(object key) {
    object o = container.Get(key) ?? "null";
    return o.ToString();
}

очевидно, эти две последовательности эквивалентны:

foo = bar != null ? bar : baz;
foo = bar ?? baz;

Вторая просто более лаконична.

1
ответ дан 28 November 2019 в 22:08
поделиться

В вашем случае вы можете создать DefaultObject как статическое свойство и использовать, как показано ниже ...

var x = (someObject as someType ?? someType.DefaultObject).someMember;

Где ваш DefaultObject будет возвращать статический объект только для чтения.

Например, EventArgs.Empty, String.Empty и т. Д. ...

1
ответ дан 28 November 2019 в 22:08
поделиться

У меня была точно такая же проблема, как и у вас, но при использовании LinqToXML тега может не быть в документе, поэтому использование ?? нецелесообразно для использования свойства этого тега.

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

Даже простой метод получения свойств, например:

MyObject MyObj() { get { return _myObj ?? new MyObj(); } }

Вероятно, лучше обслуживается инициализатором ...

Я полагаю, что, как и в SQL, он был бы полезен в запросах Linq, но я не могу действительно получить один в данный момент.

0
ответ дан 28 November 2019 в 22:08
поделиться

Я использую оператор объединения с нулем часто при синтаксическом анализе строк в другие типы данных. У меня есть набор методов расширения, которые обертывают такие вещи, как Int32.TryParse, и возвращают обнуляемый int вместо того, чтобы предоставлять выходной параметр остальной части моего кода. Затем я могу проанализировать строку и указать значение по умолчанию, если синтаксический анализ завершился неудачно, в одной строке кода.

// ToNullableInt(), is an extension method on string that returns null
// if the input is null and returns null if Int32.TryParse fails.

int startPage = Request.QueryString["start"].ToNullableInt() ?? 0;
0
ответ дан 28 November 2019 в 22:08
поделиться

The most useful is when dealing with nullable types.

bool? whatabool;
//...
bool realBool = whatabool ?? false;

without ?? you would need to write the following, which is much more confusing.

bool realbool = false;
if (whatabool.HasValue)
    realbool = whatabool.Value;

I find this operator very useful for nullable types, but other than that I don't find myself using it very much. Definitely a cool shortcut.

2
ответ дан 28 November 2019 в 22:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: