将数组变量和其他变量传入和传出 VB.Net 子例程方法

Passing array variables and other variables in and out of VB.Net Subroutine methods

我正在转录代码,它处理复数数组,从 VB 6 到 VB.Net 形式。语言语法变得更加严格,我已经非常仔细地研究了 ByVal 和 ByRef 关键字的使用,以便我可以根据需要不更改或更改通过方法子例程的变量。然而,似乎 VB 6 曾经允许我将空变量传递到子例程中,并在调用行中接收更改的(内部计算的)变量。 VB.Net 似乎不允许将空变量作为规则传递到方法子例程中?在我下面分享的代码片段中,我只能通过任意将初始值设置为实际上真正定义在方法子例程中的参数来避免调用空异常。有没有办法避免这种不雅的开销?

    Module Module1
    Sub Main()
        Dim Sx As Double() = {-0.0053, 0.8882, 0.8882, -0.0053}
        Dim Sy As Double() = {-0.0102, -0.4594, -0.4594, -0.0102}
        Dim Tx As Double() = {1.0, 1.0, 1.0, 1.0} 'To be calculated by method Stot and passed back to Main!
        Dim Ty As Double() = {1.0, 1.0, 1.0, 1.0} 'To be calculated by method Stot and passed back to Main!
        Stot(Sx, Sy, Tx, Ty) '[STh]--->[TTh]
        Console.WriteLine(Tx(0))
        Console.WriteLine(Ty(0))
        Console.WriteLine(Tx(1))
        Console.WriteLine(Ty(1))
        Console.WriteLine(Tx(2))
        Console.WriteLine(Ty(2))
        Console.WriteLine(Tx(3))
        Console.WriteLine(Ty(3))
        Stop
    End Sub
    Public Sub Stot(ByVal Sx As Double(), ByVal Sy As Double(), ByRef Tx As Double(), ByRef Ty As Double())
        Dim AA As Double
        Dim BB As Double
        Dim C As Double
        Dim D As Double
        Call Cmult(Sx(0), Sy(0), Sx(3), Sy(3), AA, BB)
        Call Cdiv(AA, BB, Sx(1), Sy(1), C, D) '(S11*S22)/S21
        Tx(0) = Sx(2) - C 'S12-((S11*S22)/S21)
        Ty(0) = Sy(2) - D
        Call Cdiv(Sx(0), Sy(0), Sx(1), Sy(1), Tx(2), Ty(2)) 'T12=S11/S21
        Call Cdiv(Sx(3), Sy(3), Sx(1), Sy(1), Tx(1), Ty(1)) 'T21=S22/S21
        Tx(1) = -1 * Tx(1) 'T21=-1*(S22/S21)
        Ty(1) = -1 * Ty(1)
        Call Cdiv(1, 0, Sx(1), Sy(1), Tx(3), Ty(3)) 'T22=1/S21
    End Sub
    Public Sub Cdiv(ByVal X1 As Double, ByVal Y1 As Double, ByVal X2 As Double, ByVal Y2 As Double, ByRef X3 As Double, ByRef Y3 As Double)
        Dim Denom As Double
        Denom = X2 * X2 + Y2 * Y2 'Multiplication by conjugate (X2+iY2)(X2-iY2)
        X3 = (X1 * X2 + Y1 * Y2) / Denom
        Y3 = (Y1 * X2 - X1 * Y2) / Denom
    End Sub
    Public Sub Cmult(ByVal X1 As Double, ByVal Y1 As Double, ByVal X2 As Double, ByVal Y2 As Double, ByRef X3 As Double, ByRef Y3 As Double)
        X3 = X1 * X2 - Y1 * Y2
        Y3 = X1 * Y2 + Y1 * X2
    End Sub
End Module

子程序StoT正在将S参数矩阵转换为T参数矩阵:常见的微波工程任务。它在做什么并不重要,它只是一个例子:如何在 VB.Net 中编写这种形式的数据共享才是重点。此控制台应用程序将数组参数定义为 Double():双精度数数组 - 复数的 X 和 Y 分量的单独数组(在 Main 方法中)。我知道数组会自动符合 VB.Net 中的引用类型,因此无需在调用的子例程中将传递的参数定义为 ByVal 或 ByRef:StoT。我再次重申:我只能通过在主定义中为输出参数 Tx() 和 Ty() 预定义任意值,在不调用 StoT 内的空异常的情况下使此调用工作。 为了完成所需的算术任务,方法 StoT 需要执行复杂的除法和复杂的乘法任务,这些任务在方法子例程中编码:CDiv() 和 CMult()。同样,这些接受并提供输出双精度数字,遵循只能使用 ByRef 关键字提供数字作为输出数字的规则。然而,这些调用不会调用空异常,即使它们生成的答案复数不是预先存在的。所以我的问题是为什么会这样。好像有点不一致....

我早就忘记了这在 VB6 中的工作方式是否不同,但在 .NET 中,当您传递 Array ByRef 时,您可以将参数分配给被调用的 完全不同的 数组方法。所以如果你传入Nothing,你可以分配一个新的Array并将新的Array分配给ByRef参数。像这样:

Module Module1
    Sub Main()
        Dim Sx As Double() = {-0.0053, 0.8882, 0.8882, -0.0053}
        Dim Sy As Double() = {-0.0102, -0.4594, -0.4594, -0.0102}
        Dim Tx As Double() = Nothing '{1.0, 1.0, 1.0, 1.0} 'To be calculated by method Stot and passed back to Main!
        Dim Ty As Double() = Nothing '{1.0, 1.0, 1.0, 1.0} 'To be calculated by method Stot and passed back to Main!
        Stot(Sx, Sy, Tx, Ty) '[STh]--->[TTh]
        Console.WriteLine(Tx(0))
        Console.WriteLine(Ty(0))
        Console.WriteLine(Tx(1))
        Console.WriteLine(Ty(1))
        Console.WriteLine(Tx(2))
        Console.WriteLine(Ty(2))
        Console.WriteLine(Tx(3))
        Console.WriteLine(Ty(3))
        Stop
    End Sub
    Public Sub Stot(ByVal Sx As Double(), ByVal Sy As Double(), ByRef Tx As Double(), ByRef Ty As Double())
        Dim AA As Double
        Dim BB As Double
        Dim C As Double
        Dim D As Double

        If IsNothing(Tx) Then
            Tx = New Double() {1.0, 1.0, 1.0, 1.0}
        End If
        If IsNothing(Ty) Then
            Ty = New Double() {1.0, 1.0, 1.0, 1.0}
        End If

        Call Cmult(Sx(0), Sy(0), Sx(3), Sy(3), AA, BB)
        Call Cdiv(AA, BB, Sx(1), Sy(1), C, D) '(S11*S22)/S21
        Tx(0) = Sx(2) - C 'S12-((S11*S22)/S21)
        Ty(0) = Sy(2) - D
        Call Cdiv(Sx(0), Sy(0), Sx(1), Sy(1), Tx(2), Ty(2)) 'T12=S11/S21
        Call Cdiv(Sx(3), Sy(3), Sx(1), Sy(1), Tx(1), Ty(1)) 'T21=S22/S21
        Tx(1) = -1 * Tx(1) 'T21=-1*(S22/S21)
        Ty(1) = -1 * Ty(1)
        Call Cdiv(1, 0, Sx(1), Sy(1), Tx(3), Ty(3)) 'T22=1/S21
    End Sub
    Public Sub Cdiv(ByVal X1 As Double, ByVal Y1 As Double, ByVal X2 As Double, ByVal Y2 As Double, ByRef X3 As Double, ByRef Y3 As Double)
        Dim Denom As Double
        Denom = X2 * X2 + Y2 * Y2 'Multiplication by conjugate (X2+iY2)(X2-iY2)
        X3 = (X1 * X2 + Y1 * Y2) / Denom
        Y3 = (Y1 * X2 - X1 * Y2) / Denom
    End Sub
    Public Sub Cmult(ByVal X1 As Double, ByVal Y1 As Double, ByVal X2 As Double, ByVal Y2 As Double, ByRef X3 As Double, ByRef Y3 As Double)
        X3 = X1 * X2 - Y1 * Y2
        Y3 = X1 * Y2 + Y1 * X2
    End Sub
End Module