🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Visual Basic 中的过程&函数 > 原文: [https://zetcode.com/lang/visualbasic/procedures/](https://zetcode.com/lang/visualbasic/procedures/) 在本部分中,您将学习 Visual Basic 过程&函数。 我们使用过程和函数来创建模块化程序。 Visual Basic 语句分组在由`Sub`,`Function`和匹配的`End`语句包围的块中。 两者之间的区别在于函数返回值,过程不返回值。 过程和函数是较大程序中的一段代码。 他们执行特定任务。 使用过程和函数的优点是: * 减少代码重复 * 将复杂的问题分解成更简单的部分 * 提高代码的清晰度 * 重用代码 * 信息隐藏 ## 过程 过程是`Sub`,`End Sub`语句内的 Visual Basic 语句块。 过程不返回值。 ```vb 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 程序的入口点。 ```vb SimpleProcedure() ``` 每个过程都有一个名称。 在`Main()`过程中,我们调用了用户定义的`SimpleProcedure()`过程。 ```vb Sub SimpleProcedure() Console.WriteLine("Simple procedure") End Sub ``` 程序在`Main()`程序之外定义。 过程名称位于`Sub`语句之后。 当我们在 Visual Basic 程序中调用过程时,该过程将得到控制。 执行该过程块内的语句。 过程可以采用可选参数。 ```vb 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()`过程。 ```vb Addition(x, y) ``` 在这里,我们将调用`Addition()`过程并将两个参数传递给它。 这些参数是两个`Integer`值。 ```vb Sub Addition(ByVal k As Integer, ByVal l As Integer) Console.WriteLine(k+l) End Sub ``` 我们定义了过程签名。 过程签名是一种描述参数和参数类型的方法,通过该方法可以对函数进行合法调用。 它包含过程的名称,其参数及其类型,对于函数,还包含返回值。 `ByVal`关键字指定我们如何将值传递给过程。 在我们的例子中,该过程获得两个数值 55 和 32。将这些数字相加并将结果打印到控制台。 ## 函数 函数是`Function`,`End Function`语句内的 Visual Basic 语句块。 函数返回值。 有两种基本类型的函数。 内置函数和用户定义的函数。 内置函数是 Visual Basic 语言的一部分。 有各种数学,字符串或转换函数。 ```vb 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 ``` 在前面的示例中,我们使用两个数学函数和一个字符串函数。 内置函数可帮助程序员完成一些常见任务。 在下面的示例中,我们有一个用户定义的函数。 ```vb 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()`函数。 ```vb result = Addition(x, y) ``` 调用加法函数。 该函数返回结果,并将该结果分配给结果变量。 ```vb Function Addition(ByVal k As Integer, _ ByVal l As Integer) As Integer Return k+l End Function ``` 这是加法函数签名及其主体。 它还包括用于返回值的返回数据类型。 在我们的例子中是`Integer`。 使用`Return`关键字将值返回给调用方。 ## 按值传递参数,按引用传递 Visual Basic 支持将参数传递给函数的两种方法。 按值和引用。 为此,我们有两个关键字。 `ByVal`和`ByRef`。 当我们按值传递参数时,该函数仅适用于值的副本。 当我们处理大量数据时,这可能会导致性能开销。 当我们通过引用传递值时,该函数会收到对实际值的引用。 修改后,原始值会受到影响。 这种传递值的方式更加节省时间和空间。 另一方面,它更容易出错。 我们应该使用哪种方式传递参数? 这取决于实际情况。 假设我们有一组数据,即员工工资。 如果我们要计算数据的某些统计信息,则无需修改它们。 我们通过值。 如果我们处理大量数据,并且计算速度至关重要,则可以引用。 如果我们要修改数据,例如进行一些减薪或加薪,我们可以引用一下。 以下两个示例涵盖了这两个概念。 ```vb 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()`过程在`a`和`b`变量之间交换数字。 原始变量不受影响。 ```vb Dim a As Byte = 4 Dim b As Byte = 7 ``` 最初,这两个变量被启动。 ```vb Swap(a, b) ``` 我们称为`Swap()`过程。 该过程将`a`和`b`变量作为参数。 ```vb temp = a a = b b = temp ``` 在`Swap()`过程中,我们更改了值。 请注意,`a`和`b`变量是在本地定义的。 它们仅在`Swap()`程序内有效。 ```vb $ ./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()`过程中更改。 ```vb 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()`过程将更改原始值。 ```vb Sub Swap(ByRef a As Byte, ByRef b As Byte) ... End Sub ``` 现在,我们使用`ByRef`关键字来指示我们通过引用传递参数。 ```vb $ ./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()`过程确实改变了变量的值。 ## 递归 在数学和计算机科学中,递归是一种定义函数的方法,其中所定义的函数在其自己的定义内应用。 (维基百科)换句话说,递归函数调用自身以完成其工作。 递归是解决许多编程任务的一种广泛使用的方法。 一个典型的例子是阶乘的计算。 ```vb 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 ``` 在此代码示例中,我们计算两个数字的阶乘。 ```vb Return n * Factorial(n-1) ``` 在阶乘函数的主体内部,我们使用经过修改的参数调用阶乘函数。 该函数调用自身。 ```vb $ ./recursion.exe 24 3628800 ``` 这些就是结果。 ## 模块作用域,程序作用域 作用域是可以引用变量的作用域。 在过程内部声明的变量具有过程作用域。 仅在此特定过程中有效。 在模块内部声明的变量具有模块作用域。 它在模块中的任何地方都有效。 ```vb 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`具有程序作用域。 ```vb Dim a As Byte = 2 ``` 变量`a`在两个过程之外的 Example 模块内部声明。 在两个过程中均有效。 ```vb Sub Main() Dim b As Byte = 3 ... End Sub ``` 变量`b`在`Main()`过程中声明。 仅在此有效。 在第二个过程中无效。 ```vb Sub SimpleProcedure() Console.WriteLine(a) ' Console.WriteLine(b) End Sub ``` 注释打印`b`变量的语句。 如果我们取消注释该行,则该示例将无法编译。 ```vb 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()`过程中声明的变量将覆盖在模块作用域中声明的变量。 ```vb $ ./scope2.exe 3 ``` 输出。 ## 静态变量 静态变量是已静态分配的变量,其生存期遍及整个程序运行。 (维基百科)默认的局部变量在函数的连续调用中不会保留其值。 ```vb 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 次。 但是,对于函数的每次调用都会启动非静态变量。 ```vb $ ./nonstatic.exe 1 ``` 在 5 个函数调用之后,`x`变量等于 1。 首次调用函数时,静态变量仅启动一次。 之后,他们保留自己的值。 ```vb 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。 ```vb Dim Static x As Byte = 0 ``` 静态变量是使用`Static`关键字创建的。 ```vb $ ./static.exe 5 ``` 运行示例。 在 Visual Basic 教程的这一部分中,我们介绍了过程和函数。