?? Объединить для пустой строки? - PullRequest
147 голосов
/ 10 марта 2010

Я обнаруживаю, что все больше и больше проверяю строку на наличие пустых (как в "" или ноль) и условного оператора.

Текущий пример:

s.SiteNumber.IsNullOrEmpty() ? "No Number" : s.SiteNumber;

Это просто метод расширения, он эквивалентен:

string.IsNullOrEmpty(s.SiteNumber) ? "No Number" : s.SiteNumber;

Так как он пустой и не нулевой, ?? не сработает. string.IsNullOrEmpty() версия ?? была бы идеальным решением. Я думаю, что должен быть более чистый способ сделать это (я надеюсь!), Но я не мог найти это.

Кто-нибудь знает лучший способ сделать это, даже если это только в .Net 4.0?

Ответы [ 10 ]

116 голосов
/ 10 марта 2010

C # уже позволяет подставлять значения для null на ??. Итак, все, что нам нужно, это расширение, которое преобразует пустую строку в null, а затем мы используем его следующим образом:

s.SiteNumber.NullIfEmpty() ?? "No Number";
69 голосов
/ 10 марта 2010

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

Поскольку вы уже используете метод расширения, почему бы просто не создать метод, который возвращает значение или значение по умолчанию:

string result = s.SiteNumber.ConvertNullOrEmptyTo("No Number");
35 голосов
/ 10 июля 2011

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

private static string Coalesce(params string[] strings)
{
    return strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
}

Использование:

string result = Coalesce(s.SiteNumber, s.AltSiteNumber, "No Number");

EDIT: Еще более компактный способ написания этой функции:

static string Coalesce(params string[] strings) => strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
15 голосов
/ 12 апреля 2012

У меня есть пара служебных расширений, которые я люблю использовать:

public static string OrDefault(this string str, string @default = default(string))
{
    return string.IsNullOrEmpty(str) ? @default : str;
}

public static object OrDefault(this string str, object @default)
{
    return string.IsNullOrEmpty(str) ? @default : str;
}

Редактировать: Вдохновленный ответом sfsr , теперь я буду добавлять этот вариант в свою панель инструментов:

public static string Coalesce(this string str, params string[] strings)
{
    return (new[] {str})
        .Concat(strings)
        .FirstOrDefault(s => !string.IsNullOrEmpty(s));
}
6 голосов
/ 11 октября 2012

Возможно, немного более быстрый метод расширения, чем предложенный ранее:

public static string Fallback(this string @this, string @default = "")
{
    return (@this == null || @this.Trim().Length == 0) ? @default : @this;
}
5 голосов
/ 23 июня 2017

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

Я закончил с:

public static string Coalesce(this string s, Func<string> func)
{
    return String.IsNullOrEmpty(s) ? func() : s;
}

Использование:

string navigationTitle = model?.NavigationTitle.
    Coalesce(() => RemoteTitleLookup(model?.ID)). // Expensive!
    Coalesce(() => model?.DisplayName);
4 голосов
/ 22 февраля 2018

Я просто использую метод расширения NullIfEmpty, который всегда будет возвращать ноль, если строка пуста, что позволяет ?? (Нулевой оператор объединения), который будет использоваться как обычно.

public static string NullIfEmpty(this string s)
{
    return s.IsNullOrEmpty() ? null : s;
}

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

string string1 = string2.NullIfEmpty() ?? string3.NullIfEmpty() ?? string4;
3 голосов
/ 10 марта 2010

как насчет метода расширения строки ValueOrDefault ()

public static string ValueOrDefault(this string s, string sDefault)
{
    if (string.IsNullOrEmpty(s))
        return sDefault;
    return s;
}

или вернуть ноль, если строка пуста:

public static string Value(this string s)
{
    if (string.IsNullOrEmpty(s))
        return null;
    return s;
}

Хотя не пытались эти решения.

2 голосов
/ 17 января 2013

Я использую собственный метод расширения Coalesce. Так как те, кто здесь используют LINQ, и абсолютно бесполезно тратят ресурсы на операции, требующие больших затрат времени (я использую их в тесных циклах), я поделюсь своим:

public static class StringCoalesceExtension
{
    public static string Coalesce(this string s1, string s2)
    {
        return string.IsNullOrWhiteSpace(s1) ? s2 : s1;
    }
}

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

string s1 = null;
string s2 = "";
string s3 = "loudenvier";
string s = s1.Coalesce(s2.Coalesce(s3));
Assert.AreEqual("loudenvier", s);

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

0 голосов
/ 28 января 2014

Мне нравится краткость следующего метода расширения QQQ для этого, хотя, конечно, такой оператор, как? было бы лучше. Но мы можем сделать это 1, позволяя сравнивать не два, а три значения строковых опций, что время от времени требует обработки (см. Вторую функцию ниже).

#region QQ

[DebuggerStepThrough]
public static string QQQ(this string str, string value2)
{
    return (str != null && str.Length > 0)
        ? str
        : value2;
}

[DebuggerStepThrough]
public static string QQQ(this string str, string value2, string value3)
{
    return (str != null && str.Length > 0)
        ? str
        : (value2 != null && value2.Length > 0)
            ? value2
            : value3;
}


// Following is only two QQ, just checks null, but allows more than 1 string unlike ?? can do:

[DebuggerStepThrough]
public static string QQ(this string str, string value2, string value3)
{
    return (str != null)
        ? str
        : (value2 != null)
            ? value2
            : value3;
}

#endregion
...