【问题标题】:Passing array variables and other variables in and out of VB.Net Subroutine methods将数组变量和其他变量传入和传出 VB.Net 子例程方法
【发布时间】:2019-01-12 17:27:29
【问题描述】:

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

    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 关键字作为输出数字提供的规则。然而,这些调用不会调用空异常,即使它们生成了一个不预先存在的答案复数。所以我的问题是为什么会这样。好像有不一致的地方......

【问题讨论】:

  • 对不起,我不明白。如果此代码有效,您将进行哪些更改以使其引发空引用异常?

标签: arrays vb.net methods parameter-passing subroutine


【解决方案1】:

我早就忘记了这在 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

【讨论】:

  • 谢谢,这有点帮助,但实际上生活中从来没有一个问题之前的答案!看来我必须提出任意数字作为占位符才能使代码正常工作。然而,空引用似乎传递到方法 CDiv() 和 CMult(),答案被计算为方程的解,并将 ByRef 作为双精度变量传递。我还不能说你已经回答了我的问题。
  • Double 是一种值类型,因此不能是 Nothing。 Double 始终初始化为 0,因此始终分配存储空间供您写入。 Double 数组是一种引用类型,如果设置为 Nothing,则根本没有分配内存供您写入值。
  • 好的 - 实际上它在 VB.6 中确实像这样工作,但我想肯定有一些问题需要您在 VB.Net 中实现的更严格的方法?
猜你喜欢
  • 1970-01-01
  • 2019-06-14
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
相关资源
最近更新 更多