如何在 .NET 4.7 中定义具有命名字段的元组?

Sou*_*der 5 .net vb.net

我试图让一个函数返回一个带有命名字段的 ValueTuple,而不是“Item1”、“Item2”等。

查看文档我有以下功能:

Public Function MyFunction() as (Success as Boolean, Results as Boolean)
    Return (True, False)
end Function

Dim test = MyFunction()

If test.Success Then
    'Do something with test.Result
End If
Run Code Online (Sandbox Code Playgroud)

这可以编译,但如果我在 if 语句上放置断点并查看“test”,它会显示其字段为“Item1”和“Item2”。它还在运行时抛出以下异常:

System.MissingMemberException: 'Public member 'Success' on type 'ValueTuple(Of Boolean,Boolean)' not found.'
Run Code Online (Sandbox Code Playgroud)

此外,该文档仅适用于“Option Strict Off”,但我们在代码中将其打开,并且该代码无法在 Option Strict On 的情况下进行编译。

在 Option Strict On 的情况下,我尝试了以下操作:

Dim test as ValueTuple(Of Success as Boolean, Results as Boolean) = MyFunction()
Run Code Online (Sandbox Code Playgroud)

然而,它在“成功”时给出编译时错误,表示它未定义。

我的语法有错误吗?在设置 Option Strict On 时,如何定义一个变量用作具有命名字段的函数的输出?

如果相关,我的项目位于 .NET 4.6.1 中,但我已使用 NuGet 包管理器添加了 ValueTuple 包。

Eni*_*ity 4

您的问题中有一些令人困惑的事情,但大多数都很容易解决。

元组提供了与 .NET 框架中的匿名类型类似的功能,但它们的实现方式不同,我认为这种差异在这里引起了混乱。

我们看一下这段代码:

Dim x = (Success := True, Results := False)

Dim y = New With {.Success = True, .Results = False}
Run Code Online (Sandbox Code Playgroud)

第一个是元组,第二个是匿名类型。

它们都可以以类似的方式使用:

Console.WriteLine(x.Success)
Console.WriteLine(y.Success)

Console.WriteLine(x.Results)
Console.WriteLine(y.Results)
Run Code Online (Sandbox Code Playgroud)

然而,在幕后,它们的构造不同。

以下是反编译后的相同代码(与 C# 一样,因为这是我的工具生成的所有代码):

(bool, bool) valueTuple = (true, false);
VB$AnonymousType_0<bool, bool> vB$AnonymousType_ = new VB$AnonymousType_0<bool, bool>(Success: true, Results: false);
Console.WriteLine(valueTuple.Item1);
Console.WriteLine(vB$AnonymousType_.Success);
Console.WriteLine(valueTuple.Item2);
Console.WriteLine(vB$AnonymousType_.Results);
Run Code Online (Sandbox Code Playgroud)

请注意,元组具有属性Item1Item2(实际上它们是字段),但匿名类型具有属性SuccessResults

命名元组字段只是编译器的诡计!反映类型不会返回源中使用的名称。

匿名类型确实会创建具有来自源的可反射名称的属性的对象。

尝试这个:

Console.WriteLine(String.Join(", ", x.GetType().GetFields().Select(Function(z) z.Name)))
Console.WriteLine(String.Join(", ", y.GetType().GetProperties().Select(Function(z) z.Name)))
Run Code Online (Sandbox Code Playgroud)

我得到:

项目1、项目2
成功、结果

元组方法允许我这样写:

Dim w As (Apple As Boolean, Banana As Boolean) = x

Console.WriteLine(w.Apple)
Console.WriteLine(w.Banana)
Run Code Online (Sandbox Code Playgroud)

你不能用匿名类型来做到这一点。

在您的问题中,您说您在运行代码时遇到运行时错误。我的电脑上看不到这个。您的第一批代码运行良好。