跳转至

Visual Basic 中的过程&函数

原文: https://zetcode.com/lang/visualbasic/procedures/

在本部分中,您将学习 Visual Basic 过程&函数。

我们使用过程和函数来创建模块化程序。 Visual Basic 语句分组在由SubFunction和匹配的End语句包围的块中。 两者之间的区别在于函数返回值,过程不返回值。

过程和函数是较大程序中的一段代码。 他们执行特定任务。 使用过程和函数的优点是:

  • 减少代码重复
  • 将复杂的问题分解成更简单的部分
  • 提高代码的清晰度
  • 重用代码
  • 信息隐藏

过程

过程是SubEnd Sub语句内的 Visual Basic 语句块。 过程不返回值。

Option Strict On

Module Example

    Sub Main()

        SimpleProcedure()

    End Sub

    Sub SimpleProcedure()
        Console.WriteLine("Simple procedure")
    End Sub

End Module

此示例显示了过程的基本用法。 在我们的程序中,我们有两个过程。 Main()过程和用户​​定义的SimpleProcedure()。 众所周知,Main()过程是 Visual Basic 程序的入口点。

SimpleProcedure()

每个过程都有一个名称。 在Main()过程中,我们调用了用户定义的SimpleProcedure()过程。

Sub SimpleProcedure()
    Console.WriteLine("Simple procedure")
End Sub

程序在Main()程序之外定义。 过程名称位于Sub语句之后。 当我们在 Visual Basic 程序中调用过程时,该过程将得到控制。 执行该过程块内的语句。

过程可以采用可选参数。

Option Strict On

Module Example

    Sub Main()

        Dim x As Integer = 55
        Dim y As Integer = 32

        Addition(x, y)

    End Sub

    Sub Addition(ByVal k As Integer, ByVal l As Integer)
        Console.WriteLine(k+l)
    End Sub

End Module

在上面的示例中,我们将一些值传递给Addition()过程。

Addition(x, y)

在这里,我们将调用Addition()过程并将两个参数传递给它。 这些参数是两个Integer值。

Sub Addition(ByVal k As Integer, ByVal l As Integer)
    Console.WriteLine(k+l)
End Sub

我们定义了过程签名。 过程签名是一种描述参数和参数类型的方法,通过该方法可以对函数进行合法调用。 它包含过程的名称,其参数及其类型,对于函数,还包含返回值。 ByVal关键字指定我们如何将值传递给过程。 在我们的例子中,该过程获得两个数值 55 和 32。将这些数字相加并将结果打印到控制台。

函数

函数是FunctionEnd Function语句内的 Visual Basic 语句块。 函数返回值。

有两种基本类型的函数。 内置函数和用户定义的函数。 内置函数是 Visual Basic 语言的一部分。 有各种数学,字符串或转换函数。

Option Strict On

Module Example

    Sub Main()

        Console.WriteLine(Math.Abs(-23))
        Console.WriteLine(Math.Round(34.56))
        Console.WriteLine("ZetCode has {0} characters", _
            Len("ZetCode"))

    End Sub

End Module

在前面的示例中,我们使用两个数学函数和一个字符串函数。 内置函数可帮助程序员完成一些常见任务。

在下面的示例中,我们有一个用户定义的函数。

Option Strict On

Module Example

    Dim x As Integer = 55
    Dim y As Integer = 32

    Dim result As Integer

    Sub Main()

        result = Addition(x, y)
        Console.WriteLine(Addition(x, y))

    End Sub

    Function Addition(ByVal k As Integer, _
                       ByVal l As Integer) As Integer
        Return k+l
    End Function

End Module

两个值传递给该函数。 我们将这两个值相加,然后将结果返回到Main()函数。

result = Addition(x, y)

调用加法函数。 该函数返回结果,并将该结果分配给结果变量。

Function Addition(ByVal k As Integer, _
                    ByVal l As Integer) As Integer
    Return k+l
End Function

这是加法函数签名及其主体。 它还包括用于返回值的返回数据类型。 在我们的例子中是Integer。 使用Return关键字将值返回给调用方。

按值传递参数,按引用传递

Visual Basic 支持将参数传递给函数的两种方法。 按值和引用。 为此,我们有两个关键字。 ByValByRef。 当我们按值传递参数时,该函数仅适用于值的副本。 当我们处理大量数据时,这可能会导致性能开销。

当我们通过引用传递值时,该函数会收到对实际值的引用。 修改后,原始值会受到影响。 这种传递值的方式更加节省时间和空间。 另一方面,它更容易出错。

我们应该使用哪种方式传递参数? 这取决于实际情况。 假设我们有一组数据,即员工工资。 如果我们要计算数据的某些统计信息,则无需修改它们。 我们通过值。 如果我们处理大量数据,并且计算速度至关重要,则可以引用。 如果我们要修改数据,例如进行一些减薪或加薪,我们可以引用一下。

以下两个示例涵盖了这两个概念。

Option Strict On

Module Example

    Dim a As Byte = 4
    Dim b As Byte = 7

    Sub Main()

        Console.WriteLine("Outside Swap procedure")
        Console.WriteLine("a is {0}", a)
        Console.WriteLine("b is {0}", b)

        Swap(a, b)

        Console.WriteLine("Outside Swap procedure")
        Console.WriteLine("a is {0}", a)
        Console.WriteLine("b is {0}", b)

    End Sub

    Sub Swap(ByVal a As Byte, ByVal b As Byte) 
        Dim temp As Byte
        temp = a
        a = b
        b = temp
        Console.WriteLine("Inside Swap procedure")
        Console.WriteLine("a is {0}", a)
        Console.WriteLine("b is {0}", b)
    End Sub

End Module

Swap()过程在ab变量之间交换数字。 原始变量不受影响。

Dim a As Byte = 4
Dim b As Byte = 7

最初,这两个变量被启动。

Swap(a, b)

我们称为Swap()过程。 该过程将ab变量作为参数。

temp = a
a = b
b = temp

Swap()过程中,我们更改了值。 请注意,ab变量是在本地定义的。 它们仅在Swap()程序内有效。

$ ./swap1.exe 
Outside Swap procedure
a is 4
b is 7
Inside Swap procedure
a is 7
b is 4
Outside Swap procedure
a is 4
b is 7

输出显示原始变量不受影响。

下一个代码示例通过引用将值传递给函数。 原始变量在Swap()过程中更改。

Option Strict On

Module Example

    Dim a As Byte = 4
    Dim b As Byte = 7

    Sub Main()

        Console.WriteLine("Outside Swap procedure")
        Console.WriteLine("a is {0}", a)
        Console.WriteLine("b is {0}", b)

        Swap(a, b)

        Console.WriteLine("Outside Swap procedure")
        Console.WriteLine("a is {0}", a)
        Console.WriteLine("b is {0}", b)

    End Sub

    Sub Swap(ByRef a As Byte, ByRef b As Byte) 
        Dim temp As Byte
        temp = a
        a = b
        b = temp
        Console.WriteLine("Inside Swap procedure")
        Console.WriteLine("a is {0}", a)
        Console.WriteLine("b is {0}", b)
    End Sub

End Module

在此示例中,调用Swap()过程将更改原始值。

Sub Swap(ByRef a As Byte, ByRef b As Byte) 
 ...  
End Sub

现在,我们使用ByRef关键字来指示我们通过引用传递参数。

$ ./swap2.exe 
Outside Swap procedure
a is 4
b is 7
Inside Swap procedure
a is 7
b is 4
Outside Swap procedure
a is 7
b is 4

在这里,我们看到Swap()过程确实改变了变量的值。

递归

在数学和计算机科学中,递归是一种定义函数的方法,其中所定义的函数在其自己的定义内应用。 (维基百科)换句话说,递归函数调用自身以完成其工作。 递归是解决许多编程任务的一种广泛使用的方法。

一个典型的例子是阶乘的计算。

Option Strict On

Module Example

    Sub Main()

        Console.WriteLine(Factorial(4))
        Console.WriteLine(Factorial(10))

    End Sub

    Function Factorial(ByVal n As UShort) As UShort
        If (n=0)
            Return 1
        Else
            Return n * Factorial(n-1)
        End If 

    End Function

End Module

在此代码示例中,我们计算两个数字的阶乘。

Return n * Factorial(n-1)

在阶乘函数的主体内部,我们使用经过修改的参数调用阶乘函数。 该函数调用自身。

$ ./recursion.exe 
24
3628800

这些就是结果。

模块作用域,程序作用域

作用域是可以引用变量的作用域。 在过程内部声明的变量具有过程作用域。 仅在此特定过程中有效。 在模块内部声明的变量具有模块作用域。 它在模块中的任何地方都有效。

Option Strict On

Module Example

    Dim a As Byte = 2

    Sub Main()
        Dim b As Byte = 3         

        Console.WriteLine(a)
        SimpleProcedure()

    End Sub

    Sub SimpleProcedure()
        Console.WriteLine(a)
        ' Console.WriteLine(b)
    End Sub

End Module

在前面的示例中,我们声明了两个变量。 变量a具有模块作用域,变量b具有程序作用域。

Dim a As Byte = 2

变量a在两个过程之外的 Example 模块内部声明。 在两个过程中均有效。

Sub Main()
    Dim b As Byte = 3         
...
End Sub

变量bMain()过程中声明。 仅在此有效。 在第二个过程中无效。

Sub SimpleProcedure()
    Console.WriteLine(a)
    ' Console.WriteLine(b)
End Sub

注释打印b变量的语句。 如果我们取消注释该行,则该示例将无法编译。

Option Strict On

Module Example

    Dim a As Byte = 2

    Sub Main()
        Dim a As Byte = 3         

        Console.WriteLine(a)

    End Sub

End Module

在前面的示例中,我们在两个不同的作用域中声明了一个具有相同名称的变量。 它们不会碰撞。 在Main()过程中声明的变量将覆盖在模块作用域中声明的变量。

$ ./scope2.exe 
3

输出。

静态变量

静态变量是已静态分配的变量,其生存期遍及整个程序运行。 (维基百科)默认的局部变量在函数的连续调用中不会保留其值。

Option Strict On

Module Example

    Sub Main()

        NonStatic()
        NonStatic()
        NonStatic()
        NonStatic()
        Console.WriteLine(NonStatic)

    End Sub

    Function NonStatic() As Integer
        Dim x As Integer = 0
        x += 1
        Return x
    End Function

End Module

在上面的示例中,我们有一个普通的非静态变量。 每次调用函数时,我们都会增加变量。 我们调用该函数 5 次。 但是,对于函数的每次调用都会启动非静态变量。

$ ./nonstatic.exe 
1

在 5 个函数调用之后,x变量等于 1。

首次调用函数时,静态变量仅启动一次。 之后,他们保留自己的值。

Option Strict On

Module Example

    Sub Main()

        StaticFunction()
        StaticFunction()
        StaticFunction()
        StaticFunction()
        Console.WriteLine(StaticFunction)

    End Sub

    Function StaticFunction() As Integer
        Dim Static x As Integer = 0
        x += 1
        Return x
    End Function

End Module

连续 5 次通话后,x等于 5。

Dim Static x As Byte = 0

静态变量是使用Static关键字创建的。

$ ./static.exe 
5

运行示例。

在 Visual Basic 教程的这一部分中,我们介绍了过程和函数。



回到顶部