是否与空合并运算符“相反”? (...用任何语言?)

时间:2010-05-28 14:24:32

标签: c# programming-languages syntax operators null-coalescing-operator

null coalescing大致翻译为return x, unless it is null, in which case return y

我经常需要return null if x is null, otherwise return x.y

我可以使用return x == null ? null : x.y;

不错,但中间的null总是困扰我 - 这似乎是多余的。我更喜欢return x :: x.y;之类的内容,::之后的内容仅在其前面的内容不是null时进行评估。

我认为这是几乎与null合并相反,有点简洁,内联空检查,但我[几乎]确定C#中没有这样的运算符。

是否有其他语言有这样的运营商?如果是这样,它叫什么?

(我知道我可以在C#中为它编写一个方法;我使用return NullOrValue.of(x, () => x.y);,但是如果你有更好的东西,我也希望看到它。) < / p>

12 个答案:

答案 0 :(得分:60)

Groovy中有 null-safe解除引用运算符(?。)......我认为这就是你所追求的。

(它也被称为safe navigation operator。)

例如:

homePostcode = person?.homeAddress?.postcode

如果personperson.homeAddressperson.homeAddress.postcode为空,则此值为空。

(现在是available in C# 6.0但在早期版本中没有)

答案 1 :(得分:33)

我们考虑过加入?到C#4。它没有削减;这是一个“很高兴”的功能,而不是“必备”功能。我们将再次考虑该语言的假设未来版本,但如果我是你,我不会屏住呼吸。随着时间的推移,它不太可能变得更加重要。 : - )

答案 2 :(得分:16)

如果你有一种特殊的短路布尔逻辑,你可以这样做(javascript示例):

return x && x.y;

如果x为空,则不会评估x.y

答案 3 :(得分:7)

将此作为答案加入是正确的。

我想在C#中没有这样的东西的原因是因为,与合并运算符(仅对引用类型有效)不同,反向操作可以产生引用或值类型(即class x成员int y - 因此很遗憾在许多情况下无法使用。

但是,我并不是说我不想看到它!

该问题的潜在解决方案是,操作员可以自动将右侧的值类型表达式提升为可空。但是你遇到的问题x.y其中y是一个int实际上会返回一个int?,这将是一个痛苦。

另一个可能更好的解决方案是,如果左边的表达式为null,则操作符将返回右侧类型的默认值(即null或0)。但是,您有一些问题可以区分实际从x.y读取零/ null的情况,或者它是否由安全访问运算符提供。

答案 4 :(得分:6)

Delphi有:(而不是。)运算符,它是null安全的。

他们正考虑添加一个?操作员对C#4.0做了同样的事情,但是得到了斩波块。

In the meantime, there's IfNotNull()哪种划痕痒。它肯定比大?或者:但它确实允许你组成一个操作链,如果其中一个成员为空,则不会对你产生NullReferenceException。

答案 5 :(得分:3)

在Haskell中,您可以使用>>运算符:

  • Nothing >> NothingNothing
  • Nothing >> Just 1Nothing
  • Just 2 >> NothingNothing
  • Just 2 >> Just 1Just 1

答案 6 :(得分:3)

Haskell有fmap,在这种情况下我认为相当于Data.Maybe.map。 Haskell纯粹是功能性的,所以你要找的是

fmap select_y x

如果xNothing,则返回Nothing。如果xJust object,则返回Just (select_y object)。不像点符号那么漂亮,但鉴于它是一种功能语言,风格是不同的。

答案 7 :(得分:2)

PowerShell让你在空引用上引用属性(但不是调用方法),如果实例为null,它将返回null。你可以在任何深度做到这一点。我曾希望C#4的动态功能支持这一功能,但事实并非如此。

$x = $null
$result = $x.y  # $result is null

$x = New-Object PSObject
$x | Add-Member NoteProperty y 'test'
$result = $x.y  # $result is 'test'

它并不漂亮但你可以添加一个扩展方法,它将以你描述的方式运行。

public static TResult SafeGet<T, TResult>(this T obj, Func<T, TResult> selector) {
    if (obj == null) { return default(TResult); }
    else { return selector(obj); }
}

var myClass = new MyClass();
var result = myClass.SafeGet(x=>x.SomeProp);

答案 8 :(得分:1)

在某处创建一个类的静态实例,并为成员创建所有正确的默认值。

例如:

z = new Thingy { y=null };

然后代替你的

return x != null ? x.y : null;

你可以写

return (x ?? z).y;

答案 9 :(得分:1)

public class ok<T> {
    T s;
    public static implicit operator ok<T>(T s) { return new ok<T> { s = s }; }
    public static implicit operator T(ok<T> _) { return _.s; }

    public static bool operator true(ok<T> _) { return _.s != null; }
    public static bool operator false(ok<T> _) { return _.s == null; }
    public static ok<T> operator &(ok<T> x, ok<T> y) { return y; }
}

我经常需要这个逻辑用于字符串:

using ok = ok<string>;

...

string bob = null;
string joe = "joe";

string name = (ok)bob && bob.ToUpper();   // name == null, no error thrown
string boss = (ok)joe && joe.ToUpper();   // boss == "JOE"

答案 10 :(得分:1)

这是在C#vNext中添加的(Roslyn支持的C#,使用Visual Studio 2014发布)。

它被称为Null传播,在此处列为完整。 https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status

此处也列为完整: https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c

答案 11 :(得分:1)

所谓的&#34;零条件运算符&#34;已在C#6.0和Visual Basic 14中引入 在许多情况下,它可以与null-coalescing运算符完全相反:

int? length = customers?.Length; // null if customers is null   
Customer first = customers?[0];  // null if customers is null  
int? count = customers?[0]?.Orders?.Count();  // null if customers, the first customer, or Orders is null

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators