184

我发现自己做的越来越多的事情是检查字符串是否为空(如 in""或 null)和条件运算符。

当前的示例:

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

这只是一个扩展方法,相当于:

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

因为它是空的而不是空的,??所以不会成功。一个string.IsNullOrEmpty()版本??将是完美的解决方案。我认为必须有一种更清洁的方式来做到这一点(我希望!),但我一直不知所措。

有没有人知道更好的方法来做到这一点,即使它只在.Net 4.0 中?

4

11 回答 11

168

C# 已经允许我们用值替换nullwith ??。所以我们只需要一个将空字符串转换为 的扩展,null然后我们像这样使用它:

s.SiteNumber.NullIfEmpty() ?? "No Number";

扩展类:

public static class StringExtensions
{
    public static string NullIfEmpty(this string s)
    {
        return string.IsNullOrEmpty(s) ? null : s;
    }
    public static string NullIfWhiteSpace(this string s)
    {
        return string.IsNullOrWhiteSpace(s) ? null : s;
    }
}
于 2010-03-10T20:23:32.123 回答
80

没有内置的方法可以做到这一点。但是,您可以使您的扩展方法返回一个字符串或 null,这将允许合并运算符工作。然而,这会很奇怪,我个人更喜欢你目前的方法。

既然您已经在使用扩展方法,为什么不制作一个返回值或默认值的方法:

string result = s.SiteNumber.ConvertNullOrEmptyTo("No Number");
于 2010-03-10T20:03:34.357 回答
52

我知道这是一个老问题 - 但我一直在寻找答案,但以上都不符合我的需要以及我最终使用的内容:

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

用法:

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

编辑: 编写此函数的更紧凑的方法是:

static string Coalesce(params string[] strings) => strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
于 2011-07-09T22:27:34.733 回答
16

我有几个我喜欢使用的实用程序扩展:

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));
}
于 2012-04-12T15:54:26.213 回答
8

零合并运算符的优点之一是它可以短路。当第一部分不为空时,不评估第二部分。当回退需要昂贵的操作时,这可能很有用。

我最终得到:

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);
于 2017-06-23T08:57:52.470 回答
7

我只是使用 NullIfEmpty 扩展方法,如果字符串为空,则始终返回 null 允许?(Null Coalescing Operator) 正常使用。

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

这然后允许?? 正常使用并使链接易于阅读。

string string1 = string2.NullIfEmpty() ?? string3.NullIfEmpty() ?? string4;
于 2018-02-22T11:35:19.290 回答
6

可能比之前提出的稍微快一点的扩展方法:

public static string Fallback(this string @this, string @default = "")
{
    return (@this == null || @this.Trim().Length == 0) ? @default : @this;
}
于 2012-10-11T08:47:25.723 回答
4

字符串扩展方法 ValueOrDefault() 怎么样

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

如果字符串为空,则返回 null:

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

虽然没有尝试这些解决方案。

于 2010-03-10T20:23:54.923 回答
3

我正在使用我自己的字符串 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);

我经常使用它。在第一次使用它之后你不能没有的那些“实用”功能之一:-)

于 2013-01-17T03:33:36.603 回答
0

我喜欢以下扩展方法的简洁性QQQ,尽管当然像运算符一样?会更好。但是我们可以通过允许不只比较两个而是三个字符串选项值来实现这一点,其中一个需要不时处理(见下面的第二个函数)。

#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
于 2014-01-28T19:37:36.673 回答
0

很容易将一些答案转换为具有泛型的辅助扩展类,以实现更广泛的用途:

注意:有关短路方法的说明,请参阅文斯文答案

// classic
public static string Coalesce(this string s, params string[] strings)
  => s.Coalesce(string.IsNullOrEmpty, strings);

// short-circuit compatible, for expensive string getting
public static string Coalesce(this string s, params Func<string>[] getters)
  => s.Coalesce(string.IsNullOrEmpty, getters);

// generic
public static T Coalesce<T>(this T value, Func<T, bool> isEmpty, params T[] values) where T : class
  => isEmpty(value) ? values.FirstOrDefault(val => !isEmpty(val)) : value;

// generic, short-circuit compatible
public static T Coalesce<T>(this T value, Func<T, bool> isEmpty, params Func<T>[] getters) where T : class {
  if (isEmpty(value))
    return getters
      .Select(getter => new Lazy<T>(getter))
      .FirstOrDefault(val => !isEmpty(val.Value))
      ?.Value;

  return value;
}

示例用法:

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

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

string navigationTitle = model?.NavigationTitle.
  Coalesce(() => RemoteTitleLookup(model?.ID), () => model?.DisplayName);

Player player = player1.Coalesce(p => p?.Score > 0, player2, player3);

(PS:我想我在这里使用泛型有点跑题了。我想太多了吗?)

于 2021-09-29T13:37:48.960 回答