是否有一个“空”合并运算符“相反”? (…用任何语言?)

空合并翻译大致return x, unless it is null, in which case return y

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

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

不错,但是中间的null位总是困扰我 – 看起来是多余的。 我宁愿像return x :: xy; ,只有在它之前的内容不为null才会评估::内容。

我认为这几乎是一个空合并的反面,这种混合与简洁,行内空检查,但我[ 几乎 ]确定在C#中没有这样的运算符。

还有其他语言有这样的运营商吗? 如果是这样,那叫什么?

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

在Groovy中有无效的解除引用操作符 (?。)…我想这就是你所追求的。

(也被称为安全导航操作员 。)

例如:

 homePostcode = person?.homeAddress?.postcode 

如果personperson.homeAddressperson.homeAddress.postcode为空,这将会为null。

(现在在C#6.0中可用,但在早期版本中不可用)

我们考虑join? 到C#4.它并没有削减; 这是一个“很好有”的function,而不是“必须有”的function。 我们会再次考虑假设的未来版本的语言,但如果我是你,我不会屏住呼吸。 随着时间的推移,这不可能变得更为重要。 🙂

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

 return x && xy; 

如果x为null,那么它不会评估xy

把这个作为答案是正确的。

我猜为什么在C#中没有这样的事情是因为,不像合并运算符(它只对引用types有效),反向操作可能会产生引用或值types(即class x与成员int y – 因此不幸的是在很多情况下都不能使用。

不过,我不是说我不想看到它!

对于这个问题的一个潜在的解决scheme是操作员可以自动提升右侧的值typesexpression式为可空。 但是,那么你有问题,其中y是一个int的xy实际上会返回一个int? 这将是一个痛苦。

另一个可能更好的解决方法是,如果左边的expression式为空,则操作员可以返回右侧types的默认值(即null或零)。 但是,那么你有问题区分的情况下零/ null实际上是从xy读取或者它是否由安全访问运营商提供。

Delphi有:(而不是。)运算符,它是无效的。

他们正在考虑添加一个? 运营商到C#4.0做同样的事情,但那得到了砧板。

与此同时,有IfNotNull()哪种划痕痒。 它肯定比?更大。 或者:但是它确实让你编写了一个操作链,如果其中一个成员是null,那么这个操作链不会在你的NullReferenceException中出现。

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

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

Haskell有fmap ,在这种情况下,我认为它相当于Data.Maybe.map 。 Haskell是纯粹的function,所以你正在寻找的是

 fmap select_y x 

如果xNothing ,则返回Nothing 。 如果xJust object ,则返回Just (select_y object) 。 不如点符号漂亮,但鉴于它是一种function性语言,样式是不同的。

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

 $x = $null $result = $xy # $result is null $x = New-Object PSObject $x | Add-Member NoteProperty y 'test' $result = $xy # $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); 

创build一个你的类的静态实例在某个地方的所有正确的默认值的成员。

例如:

 z = new Thingy { y=null }; 

那么而不是你的

 return x != null ? xy : null; 

你可以写

 return (x ?? z).y; 
 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; } } 

我经常需要这个string的逻辑:

 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" 

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

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

这里还列出了完整的: https : //visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c