检查值元组是不是为默认值

Posted

技术标签:

【中文标题】检查值元组是不是为默认值【英文标题】:Check if value tuple is default检查值元组是否为默认值 【发布时间】:2018-10-10 13:25:17 【问题描述】:

如何检查 System.ValueTuple 是否为默认值?粗略的例子:

(string foo, string bar) MyMethod() => default;

// Later
var result = MyMethod();
if (result is default)  // doesnt work

我可以使用 C# 7.2 的 default 语法在 MyMethod 中返回默认值。我无法检查默认情况下?这些是我尝试过的:

result is default
result == default
result is default(string, string)
result == default(string, string)

【问题讨论】:

不是返回一个“默认”元组,而是返回一个带有结果标志的元组并检查标志。这是最常见的情况之一。此外,is 用于强制转换或模式匹配。在这种情况下,您要求 equality 一旦 C# 得到它的 "Support for == and != on tuple types"、result == default((string, string))(编辑:需要额外的括号)甚至 result == default 应该可以工作,但我们还没有。 @PanagiotisKanavos 假设开发人员可能无法控制从公共方法返回的内容。至于这意味着什么,这意味着该操作没有成功返回有意义的值,只是掩饰了。正如我之前所说,问题的精神是学习 C# 语法。 @PanagiotisKanavos 它不必与已知值元组直接相关。例如,如果您使用通用方法执行某些操作,并且有时返回默认值(这对于“给我第一个匹配项,如果有的话”这样的场景是完全正确的),如果搜索的数据(通用类型) 是一个值元组吗?这是一个真实的用例。 @Wolfsblvt 该用例与返回 null、0 或其他魔法值没有什么不同。值元组通过允许使用类似 Rust 或 Go 的值元组来解决这个问题。与其返回 null 或魔法值并检查 null 或默认值,不如返回一个强类型 (result,error) 元组。这种方式更难忽略错误 【参考方案1】:

注意到答案中缺少代码和文档,因此我在 .NET 5 中尝试了一些不同的相等性检查,全部使用 ==,看看它们会如何评估。说明。

如果元组中的所有单个值都是它们自己的default 版本,那么最重要的是,元组是default。如果你新建一个元组到= default,所有的东西都设置为它自己的default版本。

这有点道理。

实际代码1

注意:此测试是在 .NET 5 控制台应用程序中执行的。

static void TupleDefault()

    (int first, string second) spam = new(1, "hello");
    (int first, string second) spam2 = default;

    Console.WriteLine(spam == default);      // False
    Console.WriteLine(spam2 == default);     // True

    Console.WriteLine(spam2.first);          // 0
    Console.WriteLine(spam2.first == 0);     // True

    Console.WriteLine(spam2.second);         // Nothing.
    Console.WriteLine(spam2.second == null); // True

    // ==== Let's try to create a default "by hand" ====
    (int first, string second) spam3 = new(0, null);

    // It works!
    Console.WriteLine(spam3 == default);     // True

【讨论】:

【参考方案2】:

如果你真的想让它返回default,你可以使用

result.Equals(default)

ValueTuple 的内置 Equals 方法应该可以工作。

从 C# 7.3 开始,值元组现在还完全支持通过 ==!= 进行比较, 这意味着您现在也可以这样做

result == default 应该是一样的。

【讨论】:

【参考方案3】:

从 C# 7.3 开始,元组类型现在支持 == 和 !=。所以你的代码可能是这样的:

(string foo, string bar) MyMethod() => default;

// Later
var result = MyMethod();
if (result == default)  // Works!

见https://docs.microsoft.com/en-us/dotnet/csharp/tuples#equality-and-tuples

【讨论】:

【参考方案4】:

有几种方法可以将默认值与值元组进行比较:

    [TestMethod]
    public void Default()
    
        (string foo, string bar) MyMethod() => default;
        (string, string) x = default;

        var result = MyMethod();

        // These from your answer are not compilable
        // Assert.IsFalse(x == default);
        // Assert.IsFalse(x == default(string string));
        // Assert.IsFalse(x is default);
        // Assert.IsFalse(x is default(string string));

        Assert.IsFalse(Equals(x, default));
        Assert.IsFalse(Equals(result, default));

        Assert.IsTrue(Equals(x, default((string, string))));
        Assert.IsTrue(Equals(result, default((string, string))));
        Assert.IsTrue(result.Equals(default));
        Assert.IsTrue(x.Equals(default));
        Assert.IsTrue(result.Equals(default((string, string))));
        x.Equals(default((string, string)))
    

一个简单的default在用于比较之前必须从它的“纯”null具体化为一个具有成员默认值的值元组。

这是我在调试器下的内容:

【讨论】:

感谢您的详细解答。在最后一行中,我认为您的意思是 x.Equals(default((string, string))) 而不是 Equals(x, default((string, string))) 其实这两种情况都通过了。 我知道两者都通过了,但你已经复制了两次Equals(x, default((string, string)))。只是说。【参考方案5】:

你的尝试有两个问题:

    元组上没有定义 == 运算符(在 C# 7.2 中) 要获取元组类型的默认值,您需要正确地将类型括起来:default((int, int))

请注意,== 运算符已添加到 C# 7.3 中的元组中。然后你可以做tuple == default(见live example)。

【讨论】:

我不认为第 2 点是正确的。 defaultdefault(T) 的替代品。 @nawfal 抱歉,我不清楚。我指的是default(string, string),这是无效的语法(缺少括号)。

以上是关于检查值元组是不是为默认值的主要内容,如果未能解决你的问题,请参考以下文章

C#关键字扫盲——Tuple(元组类) ValueTuple(值元组)

将键值元组包转换为 Apache Pig 中的映射

详解C# Tuple VS ValueTuple(元组类 VS 值元组)

详解C# Tuple VS ValueTuple(元组类 VS 值元组)

详解C# Tuple VS ValueTuple(元组类 VS 值元组)

Presto 检查是不是为 NULL 并返回默认值(NVL 模拟)