无效合并大致转化为 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);, ,但是如果您有更好的东西,我也想看看。)

有帮助吗?

解决方案

NULL-SAFE DERECERCING OPITOR (?。)在Groovy ...我认为这就是您所追求的。

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

例如:

homePostcode = person?.homeAddress?.postcode

如果这将使无效 person, person.homeAddress 或者 person.homeAddress.postcode 一片空白。

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

其他提示

我们考虑添加?到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 >> NothingNothing
  • Nothing >> Just 1Nothing
  • Just 2 >> NothingNothing
  • Just 2 >> Just 1Just 1

哈斯克尔有 fmap, ,在这种情况下,我认为Data.Maybe.map. 。 Haskell纯粹是实用的,所以您要寻找的是

fmap select_y x

如果 xNothing, ,这是返回的 Nothing. 。如果 xJust 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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top