我遇到了一个有趣的案例,其中pass-by-reference似乎在VB.NET中不起作用。我在下面提供了一些示例代码供大家使用。任何人都可以解释这种现象这是预期的,还是语言/编译器的错误?
我在这段代码中看到的是“After Increment”读数与“Before Increment”读数相同。
Public Class Wrapper
Public Property Value As Integer
End Class
Sub Main()
Dim rand As New Random()
Dim w As New Wrapper()
w.Value = rand.Next()
Console.WriteLine("Before Increment: {0}", w.Value)
Try
Increment(w.Value)
Catch ex As Exception
End Try
Console.WriteLine("After Increment: {0}", w.Value)
Console.ReadLine()
End Sub
Public Sub Increment(ByRef i As Integer)
i += 1
Throw New Exception()
End Sub
我遇到了一个有趣的案例,其中pass-by-reference似乎在VB.NET中不起作用。
实际上,这是一个非常有趣的案例。
我在下面提供了一些示例代码供大家使用。任何人都可以解释这种现象
是。
这是预期的,还是语言/编译器的错误?
此行为是设计使然,它不是一个错误。你不应该写这样的VB代码。如果在执行此操作时受伤,请停止操作。
这一切都有道理,但你必须理解它的逻辑。跟着
Try
Dim Temp As Integer
Temp = w.Value ' copy-in
Increment(Temp) ' make an alias to Temp
w.Value = Temp ' copy-out
Catch ex As Exception
End Try
现在应该很清楚为什么你的程序具有它所具有的行为。抛出在复制之前发生。
人们常说C#和VB是语法不同的“同一种语言”,并且有一些道理。但是,显示小差异的示例表明语言具有不同的设计原则。 C#和VB在处理ref传递的值时不同,这不是偶然的!
C#的设计原则包括编译器应该在代码看起来错误的时候告诉你,特别是编译器不应该通过猜测你的意思来“克服”问题,并且发布代码以使其在大多数情况下工作。设计团队认为C#程序员的态度是“编译器是我的朋友,告诉我什么时候我错了所以我可以改进”。
VB的设计原则包括代码可能工作正常,如果有些东西看起来不太正确,弄清楚用户的意思并使其工作,即使这意味着引入代码,比如说,不保留对象身份,或添加隐藏的副本拷贝或其他。设计团队认为VB程序员的态度是“编译器经常阻挡我的方式;我已经表达了一个意图,所以让它工作”。
这两个设计原则都是完全合理的,每个都有大量的开发者选区。我认为,微软几十年来花费了两倍的语言开发费用,以便开发人员能够选择适合自己性格的语言,这是相当不错的。
也就是说:在C#中有些情况下编译器会做类似的事情:创建一个临时变量,为它赋值,然后通过ref传递变量。
挑战:创建一个演示这一事实的程序。
提示#1:由于某种原因,可变结构在C#中是一种不好的做法。
提示#2:在什么情况下将变量视为C#中的值?