变量声明中的 ReadOnly 有什么用?

Nos*_*omo 3 .net vb.net

我只是偶然发现了一个问题,我花了几个小时才找到原因。

我声明了一个类变量,ReadOnly因为我想在类的构造函数中设置它的值(以下所有代码都是示例代码,所以它可能没有多大意义)。

Private ReadOnly _content as String

Public Sub New(content As String)
    _content = content
End Sub

Public ReadOnly Property Content As String
    Get
        Return _content
    End Get
End Property
Run Code Online (Sandbox Code Playgroud)

经过一些编码后,我发现我想根据这个变量的值做其他事情,所以我将代码更改为:

Private ReadOnly _content as String

Public Sub New(content As String)
    Me.Content = content
End Sub

Public Property Content As String
    Get
        Return _content
    End Get
    Private Set(value As String)
        If Me.SetValue(Of String)(_content, value) AndAlso (_content = "foo") Then
            'other stuff
        End If
    End Set
End Property

Private Function SetValue(Of T)(ByRef storage As T, value As T) As Boolean
    storage = value
    Return True
End Sub
Run Code Online (Sandbox Code Playgroud)

但是这个更改后的代码不起作用,变量_content从未获得我在构造函数中传递的值。Visual Studio 2019 没有显示错误,代码编译并运行。

经过大量的反复试验,我发现,我忘记删除ReadOnly变量声明中的 ,这就是我的问题的原因。

但是,当我尝试ReadOnly在构造函数之外设置变量时,为什么 Visual Studio 不警告我这种情况,或者为什么程序不会崩溃?ReadOnly变量声明中的这有什么用,因为它只会引起混乱且难以发现错误?

xan*_*tos 7

甚至在roslynvblang的 github 上也有人问过这个问题。有一个明确的答案:

Visual Basic 语言规范的第 130 页指出:Copy-in copy-back。如果传递给引用参数的变量类型与引用参数的类型不兼容,或者如果将非变量(例如属性)作为参数传递给引用参数,或者调用是后期绑定的,然后分配一个临时变量并将其传递给引用参数。传入的值将在调用方法之前复制到此临时变量中,并在方法返回时复制回原始变量(如果有且可写)。

甚至还有一个历史理由:

这是设计使然。在 VB6 中 ByRef 是默认值,因此传递任何参数都是 ByRef,包括 ReadOnly 属性。

如果您好奇,我已经创建了一个SharpLab 示例,其中包含您的代码的简化版本(我已经删除了与您的问题无关的任何内容,并放置了另一个非ReadOnly字段进行比较),您可以在其中观察正在发生的事情。生成的 C# 代码等同于生成的 IL 代码(您可以尝试将结果语言组合框更改为 IL,但除非您涉足 IL 代码编程,否则它更不可读)。