否定空合并运算符

19

我有一堆字符串需要使用.Trim()方法,但它们可能为null。如果能像这样做,将会更加简洁:

string endString = startString !?? startString.Trim();

如果左侧部分不为NULL,则返回右侧部分,否则只返回NULL值。我最终使用了三元运算符,但是否有方法可以使用null-coalescing操作符来实现此目的?


3
我不这么认为,说实话!string.IsNullOrEmpty(startString) ? startString.Trim() : null;有什么问题吗? - flq
1
根据我的理解,您想要传播null,即如果字符串为空,则返回null;否则返回修剪后的字符串。是这样吗?如果是这种情况,没有内置的运算符或方法可以实现此操作。您可以使用三元运算符(就像您已经做过的)或编写一个方法来实现。 - Alfred Myers
我仍在等待这个运算符成为语言的一部分 :( - PedroC88
我喜欢 @sixlettervariables 的方法,即使 startString 是 null,也会返回 空字符串 - LCJ
听起来你真正需要的是一个 ?. : 三元运算符;如果左操作数非空,则访问相应成员,否则计算右侧。示例用法:theValue = someThing?.SomeProperty : defaultValue; 这将是一个有用的运算符,但它的语法和绑定与语言中的任何其他内容都完全不同。 - supercat
8个回答

13

您可以创建一个扩展方法,当尝试修剪值时返回null

public String TrimIfNotNull(this string item)
{
   if(String.IsNullOrEmpty(item))
     return item;
   else
    return item.Trim();
}

请注意,您无法将其命名为Trim,因为扩展方法无法覆盖实例方法。


item为空时,这个方法的运行感觉很不对劲...但是,我确认它可以工作。string s = null; s.TrimIfNotNull();没有像常规实例方法那样(即使不引用任何成员),会抛出NullReferenceException异常。 - Nathan Ernst
它能够正常工作完全是有道理的。扩展方法仅仅是附加到对象上的静态方法。实际上,没有理由它们不能工作。类不能依赖于它们所做的任何事情,因为它们在原始类创建时并不存在,并且它们无法访问任何私有方法或对象。不允许它们在 null 对象上使用将是妨碍性的(虽然我承认一开始可能有点奇怪)。 - kemiller2002
1
是的,该功能的高潮是IfNotNull扩展方法:public V IfNotNull<T, V>(this T @in, Func<T,V> access) - flq

12

不符合规范:虽然我不太喜欢,但你可以使用:

string endString = (startString ?? String.Empty).Trim();

按规范,最好作为扩展方法像@Kevin所述:

string endString = (startString == null ? null : startString.Trim());

5
不会传播所要求的null值。 - Alfred Myers
3
如果startString为空,这个函数不会返回null。 - Serge Wautier
1
需要我再读一遍才意识到他实际上想要的是null... 在这种情况下,@Kevin 的想法是正确的。 - user7116
为什么不使用 string.IsNullOrEmpty() - Sarah Vessels
据我了解,他希望 null 保持为 null,empty 保持为空。 - user7116
我喜欢你的第一种方法。即使 startString 为 null,也请返回空字符串。这在为文本框控件分配值时非常有用。如果您能在答案中添加这个解释,那就更好了。 - LCJ

4

从C# 6.0开始(.NET Framework 4.6 / Visual Studio 2015),你可以使用空值条件成员访问

 string? endString = startString?.Trim();

1
应该使用问号?代替句号.,请返回翻译后的文本。 - jhunter

4
string endString = string.IsNullOrEmpty(startString) ? startString : startString.Trim();

虽然我也曾经编写过一个名为“safeTrim”的字符串扩展方法,它可以一次完成您所描述的操作,而不必每次都使用此方法。查看Kevin的回答获取代码。

编辑:哇,我把所有东西都搞反了,变量名称错误,三元运算符反转,这就更需要编写一个扩展方法并检查代码,以避免像我一样的错误!


1
由于Frank的评论提醒我应该使用string.IsNullOrEmpty(foo)而不是foo.IsNullOrEmpty(),因此进行了Ninja编辑。 - Daniel DiPaolo
2
检查是否为空。这不是他要求的。 - Alfred Myers
3
endString在特定语句中定义时,它如何已经在范围内?我认为你需要进行更多的精细编辑... - Jørn Schou-Rode
1
我认为你的意思是 string endString = string.IsNullOrEmpty(startString) ? startString : startString.Trim();。如果字符串为空或者为null,他想要一个空字符串,但如果不为空,他想要去掉两端的空格。 - Sarah Vessels
1
@Sarah 确实如此,我完全搞反了,甚至在一个分支中选择了错误的变量名称,哇 headdesk - Daniel DiPaolo
显示剩余4条评论

1
抱歉打扰,但我遇到了同样的问题,并通过使用lambda操作解决了它。虽然不是最美观的方式,但它使我的代码简洁。

很遗憾C#不支持静态导入或单个函数导入,但无论如何:

在某个地方定义这个函数:

private static TResult N<TParent,TResult>(TParent parent, Func<TParent,TResult> operation) {
    if( parent == null ) return default(TResult);
    return operation( parent );
}

然后在你的例子中使用它:
String endString = N(startString, s => s.Trim());
N函数在第一个参数为空时返回null,否则将使用该值作为参数计算指定的lambda函数。当然,您可以像这样嵌套它。例如,要安全地取消引用长链,可以这样做。
String someValue = someObject.SomeProperty.SomeOtherProperty.SomeMethod().SomeFinalProperty;

如果其中任何一个属性或方法返回 null,则必须在每个地方插入 null 检查,或者您可以这样做:

String someValue = N(N(N(N(someObject, o => o.SomeProperty), o => o.SomeOtherProperty), o => o.SomeMethod()), o => o.SomeFinalProperty);

就像我说的一样,这不是最美观的 :)

你可以通过将N作为System.Object的扩展方法来简化它,像这样:

String someValue = someObject.N( o => o.SomeProperty ).N( o => o.SomeOtherProperty ).N( o => o.SomeMethod() ).N( o => o.SomeFinalProperty );

"

...我认为这样更整洁。

"

一个受类约束的泛型似乎比System.Object更好,我认为有一些接受各种数量“额外”参数的变体会很不错。在捕获任何东西(包括this)的lambda和不捕获的lambda之间可能存在巨大的性能差异,因此允许显式传递参数而不是捕获可以带来很大的优势。 - supercat

0

使用

string endString = (startString ?? "").Trim();

如果 startString 为 null,则使用空字符串。然而,当 endString 为 null 时,不会返回 null。

快进到 2021 年:
10 年后,startString?.Trim() 明显是更好的选择。而且这确实会返回 null


如果 startString 为 null,则他希望 endString 也为 null。您的示例将返回 string.Empty。 - Alfred Myers

-1

以下代码不会传播 null,但它可以接受 null 作为参数,在这种情况下返回一个空字符串。

using Microsoft.VisualBasic;  // you need to add a reference to Microsoft.VisualBasic.dll

    ...
    string endString = Strings.Trim(startString);
    ...

鸭子跑...


-1

有趣的方法,但似乎与OP所面临的问题无关。 - Brian

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