无效的运算符是否有“相反”? (…任何语言?)
-
05-10-2019 - |
题
无效合并大致转化为 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);
, ,但是如果您有更好的东西,我也想看看。)
其他提示
我们考虑添加?到c#4。这是“拥有”功能,而不是“ Gotta具有”功能。我们将再次考虑该语言的假设未来版本,但是如果我是您,我不会等待我的呼吸。随着时间的流逝,它不太可能更加重要。 :-)
如果您有一种特殊的短路布尔逻辑,则可以执行此操作(JavaScript示例):
return x && x.y;
如果 x
是无效的,那么它不会评估 x.y
.
将其添加为答案感到正确。
我想C#中没有这样的东西的原因是,与合并操作员不同(仅适用于参考类型),反向操作可以产生参考或值类型(即 class x
与会员 int y
- 因此,在许多情况下,它将无法使用。
但是,我并不是说我不想看到它!
对该问题的潜在解决方案将使操作员自动将右侧的值类型表达式自动提升为无效。但是您有一个问题 x.y
y是in的地方实际上会返回 int?
这会很痛苦。
如果操作员在左侧的表达式为null,则另一个更好的解决方案是让操作员返回右侧类型的默认值(即null或零)。但是,您就遇到了区分场景的问题 x.y
还是安全访问运营商提供的。
Delphi具有:(而不是。)操作员,这是无效的。
他们正在考虑添加?运算符到C#4.0进行相同的操作,但这有斩波块。
同时,有ifnotnull() 哪种痒痒的痒。当然比?或:,但它确实让您组成一系列操作链,如果其中一个成员为无效,则不会向您提供NullReferenceException。
在Haskell中,您可以使用 >>
操作员:
Nothing >> Nothing
是Nothing
Nothing >> Just 1
是Nothing
Just 2 >> Nothing
是Nothing
Just 2 >> Just 1
是Just 1
哈斯克尔有 fmap
, ,在这种情况下,我认为Data.Maybe.map
. 。 Haskell纯粹是实用的,所以您要寻找的是
fmap select_y x
如果 x
是 Nothing
, ,这是返回的 Nothing
. 。如果 x
是 Just object
, ,这是返回的 Just (select_y object)
. 。不像点符号那样漂亮,但是鉴于它是一种功能性语言,样式是不同的。
powerShell让您在null引用上引用属性(但不调用方法),如果实例为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);
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"
创建类的静态实例,在某个地方,所有正确的默认值为成员。
例如:
z = new Thingy { y=null };
然后而不是你的
return x != null ? x.y : null;
你可以写
return (x ?? z).y;
这是在C#vnext(Roslyn Powered 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
C#6.0和Visual Basic 14中引入了所谓的“零条件运算符”。
在许多情况下
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