.NET有将null字符串转换为String.Empty的方法吗?

6
我有一个一行代码的方法,可以将null字符串转换为string.Empty。我认为这可能会作为一个扩展方法非常有用,但我无法找到一个实用的方法来实现它。
我唯一能想到的有用方式是将其作为string类的静态方法,因为显然它不能被归属于一个实例,因为该实例是null,这会导致编译器错误。[编辑:编译器错误是由于未初始化变量,我误解了]
我考虑将其添加到帮助程序类中,但这只会从可发现性的角度增加不必要的复杂性。
所以我想这个问题基本上分为两部分:
1. .NET框架是否有内置的将null字符串解析为string.Empty的方法?我是否错过了普遍知道的东西?
2. 如果没有 - 有人知道如何将此方法添加为string类的静态扩展吗?
提前感谢您。
编辑:
好吧,我想我应该再明确一些 - 我已经非常清楚地知道了空合并运算符,而我正在使用它来检查大约十多个字符串,以计算哈希码。
正如您所想象的那样,紧密跟随着彼此的12行代码都包含了空合并语法,这是一个眼酸的事情,所以我将空合并操作移至一个方法中,以使代码更易于阅读。这是完美的,但它会成为string对象的一个完美扩展:
int hashcode =
FirstValue.ResolveNull().GetHashCode() ^
SecondValue.ResolveNull().GetHashCode() ^
...

超过十几行的代码比以下代码更易于阅读:

int hashcode =
(FirstValue ?? String.Empty).GetHashCode() ^
(SecondValue ?? String.Empty).GetHashCode() ^
...

当我没有明确将字符串值声明为null,而是依赖于隐式声明时,我遇到了编译器问题:

 string s;

如果您明确定义了以下内容:
string s = null;

您可以很容易地调用:

s.ResolveNull();

感谢大家的参与。

1
我认为不能处理空字符串的代码很丑陋 :-P - Allen Rice
谁说微软从来不写丑陋的代码了? :) - Allen Rice
1
String.GetHashCode 无法“处理” null,因为它是一个实例方法,在 C# 中,实例方法通常不应该使用 null 接收器调用。 - Pavel Minaev
@Allen 我会避开那场辩论的 :P - BenAlabaster
@Pavel 是的,可以理解一个空对象在技术上没有任何方法 - 因为没有东西可以使用方法。我错过的是你可以在空接收器上运行扩展方法,这使得事情变得更加漂亮! - BenAlabaster
显示剩余3条评论
10个回答

25

我认为没有为此内置的东西。我的第一个想法,也是我经常使用的方法,是使用coalesce运算符:

string s = null;
string x = s ?? string.Empty;

不知道为什么有人会这样做,当他们可以直接添加string.Empty时。 - Allen Rice
3
@Allen - 这在语义上非常清晰地表明用户想要一个空字符串而不是 null。如果你正在将空字符串添加到看起来已存在的字符串中,有人可能会误解代码实际上应该执行什么操作。 - John Rasch
“耸肩”我在帖子中展示了IL代码,它们是相同的,所以这取决于风格。在我看来,我的解决方案更清晰易读,但这是主观的。 - Allen Rice
1
如果有很多需要解决的行,看起来就像地狱一样丑陋,这就是为什么我想把它放到扩展方法中的原因。 - BenAlabaster
你也可以写成(s ?? ""),这可能比任何扩展方法都要短 :) - Pavel Minaev
简洁和易读并不一定相同。当你有十几行代码紧挨着且充满符号(如问号、引号和括号)时,很容易就会变得丑陋难看。 - BenAlabaster

6
我能看到它有用的唯一方式是将其作为字符串类上的静态方法,因为显然它不能归属于实例,因为实例为空,这会导致运行时错误。C# 3.0扩展方法可以在空接收器上调用(因为它们在实践中是静态的),但表现为实例方法。所以只需要将其变成扩展方法即可。

4
您提到关于在空值上调用扩展方法的观点是100%正确的(+1)-但通常这将需要比空值合并更多的努力。 - Marc Gravell
我同意,Marc - 这就是为什么我实际上投了第一个提到 ??(Matt 的)的答案。这只是为了指出问题中的错误陈述。 - Pavel Minaev
不需要对这些进行空值处理,因为它们的默认值为0(例如int类型)- 我只是遇到了字符串值的问题。 - BenAlabaster
本地变量没有默认值。本地整数不会默认为0。尝试int x; Console.WriteLine(x);并查看结果。我假设您在谈论本地变量,因为您之前提到过您正在“收到编译器错误”- 您无法收到关于null的编译器错误,但是如果未初始化本地变量,则可能会发生这种情况。 - Pavel Minaev
@Pavel:好的,我需要更多的睡眠——在理解之前我不得不读三遍,哈哈——是的,你是对的。我的测试代码使用本地变量,而我的应用程序代码使用字段,因此存在差异。 - BenAlabaster
显示剩余2条评论

4

一些涉及(s ?? "");的表达式。

关于string.Empty""之间的区别,没有必要激动不已-差别微不足道:

Console.WriteLine(ReferenceEquals(string.Empty, "")); // true

我的静态方法使用了空值合并 - 我只是想让代码更易读,因为我有十几行检查不同字段,看起来很丑陋。 - BenAlabaster

3

扩展方法:

public static class StringExtensions
{
    public static String EmptyIfNull(this String instance)
    {
        return instance ?? String.Empty;
    }
}

当然,在需要使用String.Empty而不是null的地方,您可以轻松地编写instance ?? String.Empty

我曾在计算哈希码的地方使用它,但可惜有十几个字符串字段可能为 null,看起来很丑陋。我认为将其作为字符串的静态扩展方法会更美观——即 string.ResolveNull(stringValue).GetHashCode()。 - BenAlabaster

1

1
string abc = s ?? string.Empty;

1
string test = CouldReturnNull() ?? string.Empty;

0

只需将 string.Empty 添加到任何字符串变量中,您就可以确保永远不会得到 null

string a = null;
string b = null + string.Empty;
string c = "a" + string.Empty;

(a == string.Empty).Dump(); // False
(b == string.Empty).Dump(); // True
(c == "a").Dump(); // True

我在 LinqPad 中使用了这个,因此有 .Dump()。

看看你的选项...

这种技术

string b = null + string.Empty;

生成

IL_0001:  ldsfld      System.String.Empty
IL_0006:  dup         
IL_0007:  brtrue.s    IL_000F
IL_0009:  pop         
IL_000A:  ldstr       ""
IL_000F:  stloc.0     

另一个流行的选择:

string b = null ?? string.empty

生成

IL_0001:  ldsfld      System.String.Empty
IL_0006:  stloc.0     

和这个

string b = null + "";

生成这个

IL_0001:  ldstr       ""
IL_0006:  stloc.0     

我仍然偏爱

string b = null + "";

但是,我个人认为,当您处理字符串时,您应该准备好处理 null


0

我认为将其实现为扩展方法会感觉有点像瑞典所说的"去河对岸取水"。当我需要确保获取空字符串而不是null时,我经常只需与string.Empty连接:

public void SomeMethod(string param)
{
    string notNull = param + string.Empty;
}

当然,这可能会导致创建额外的字符串实例,但在我所处的大多数现实世界情况下,这并不是一个问题。


0
没有内置函数可以完成这个功能,但你可以写一个小的扩展方法(或静态方法)来处理字符串类型,例如以下语句:
``` return s ?? string.Empty; ```

这有点麻烦,因为他在谈论分配而不是检查。但通常情况下,我会尝试使用它。 - Allen Rice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接