如何在.NET 4.7中使用命名字段定义元组?

时间:2019-07-08 19:26:43

标签: .net vb.net

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

看着the documentation,我具有以下功能:

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

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

System.MissingMemberException: 'Public member 'Success' on type 'ValueTuple(Of Boolean,Boolean)' not found.'

此外,该文档仅在“ Option Strict Off”下起作用,但是我们在代码中将其打开,并且该代码在Option Strict On下无法编译。

严格启用选项后,我尝试了以下操作:

Dim test as ValueTuple(Of Success as Boolean, Results as Boolean) = MyFunction()

但是,如果未定义“成功”,它会给出编译时错误。

我的语法是否错误?在设置Option Strict On的情况下,如何定义一个用作命名字段的函数输出的变量?

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

1 个答案:

答案 0 :(得分:1)

在您的问题中,您会遇到一些令人困惑的事情,但是大多数问题很容易解决。

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

让我们看一下这段代码:

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

Dim y = New With {.Success = True, .Results = False}

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

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

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

Console.WriteLine(x.Results)
Console.WriteLine(y.Results)

在引擎盖下,它们的结构不同。

这里是反编译的相同代码(因为我的工具生成的都是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);

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

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

匿名类型的确会创建具有属性的对象,这些属性具有源中可反射的名称。

尝试一下:

Console.WriteLine(String.Join(", ", x.GetType().GetFields().Select(Function(z) z.Name)))
Console.WriteLine(String.Join(", ", y.GetType().GetProperties().Select(Function(z) z.Name)))

我得到:

Item1, Item2
Success, Results

元组方法允许我这样写:

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

Console.WriteLine(w.Apple)
Console.WriteLine(w.Banana)

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

在您的问题中,您说您在运行代码时遇到运行时错误。我没有在计算机上得到它。您的第一批代码运行良好。