练习 - 使用值和引用类型参数
在 C# 中,变量可分为两种主要类型:值类型和引用类型。 这些类型描述变量如何存储其值。
值类型,例如int、bool、float和doublechar直接包含值。 引用类型(如string、array)和对象(如Random的实例)不会直接存储它们的值。 相反,引用类型存储其值所在的地址。
按值传递和按引用传递的参数
将参数传递给方法时, 值 类型变量的值将复制到方法中。 每个变量都有自己的值副本,因此不会修改原始变量。
使用引用类型时,值的地址将传递到方法中。 传递给方法的变量引用该地址处的值,因此对该变量的操作会影响被另一个变量引用的值。
注释
请务必记住, string 这是一个引用类型,但它是不 可变的。 这意味着,一旦为其分配了值,便无法更改该值。 在 C# 中,当方法和运算符用于修改字符串时,返回的结果实际上是一个新的字符串对象。
在本练习中,你将了解有关将引用和值类型参数传递到方法的详细信息。
对按值传递进行测试
在 Visual Studio Code 编辑器中,删除前面练习中的任何现有代码。
在 Visual Studio Code 编辑器中输入以下代码:
int a = 3; int b = 4; int c = 0; Multiply(a, b, c); Console.WriteLine($"global statement: {a} x {b} = {c}"); void Multiply(int a, int b, int c) { c = a * b; Console.WriteLine($"inside Multiply method: {a} x {b} = {c}"); }变量
a,b并c传递给Multiply方法。 变量的值在方法执行过程中打印,并在方法完成后再次打印。整数是值类型,在传入方法时复制其值。 你认为
c输出会是什么?保存并运行代码以观察以下输出:
inside Multiply method: 3 x 4 = 12 global statement: 3 x 4 = 0请注意,
c的值仅在Multiply方法中更改。 在方法之外,c保留其原始值。
对按引用传递进行测试
从 Visual Studio Code 编辑器中删除以前的代码。
在 Visual Studio Code 编辑器中输入以下代码:
int[] array = {1, 2, 3, 4, 5}; PrintArray(array); Clear(array); PrintArray(array); void PrintArray(int[] array) { foreach (int a in array) { Console.Write($"{a} "); } Console.WriteLine(); } void Clear(int[] array) { for (int i = 0; i < array.Length; i++) { array[i] = 0; } }代码开始于
array被初始化以包含一些整数值。 使用PrintArray方法显示这些值。 该方法Clear在数组上调用,然后再次打印该数组。数组是引用类型。 引用类型将其值的地址存储在内存中。 你认为输出会是什么?
保存并运行代码以观察以下输出:
1 2 3 4 5 0 0 0 0 0请注意,数组在
Clear方法范围之外仍会更改。 发生这种情况是因为Clear该方法更新了存储在每个地址中的值。
使用字符串进行测试
早些时候,你了解到字符串是 不可变 类型。 尽管字符串是引用类型,但与数组不同,在分配字符串后,无法更改其值。 如果您使用过如string.Replace或string.ToUpper等方法,您可能已经注意到这一点。 在此任务中,你将了解如何更正使用字符串时发现的常见错误。
在 Visual Studio Code 编辑器中,删除前面练习中的任何现有代码。
在 Visual Studio Code 编辑器中输入以下代码:
string status = "Healthy"; Console.WriteLine($"Start: {status}"); SetHealth(status, false); Console.WriteLine($"End: {status}"); void SetHealth(string status, bool isHealthy) { status = (isHealthy ? "Healthy" : "Unhealthy"); Console.WriteLine($"Middle: {status}"); }保存并运行代码以观察以下输出:
Start: Healthy Middle: Unhealthy End: HealthySetHealth如果方法未输出状态,则可能假定该方法未正确执行。 而是创建了一个值为“不正常”的新字符串,然后在方法的作用域内被丢弃。若要更正此问题,可以改为使用
SetHealth全局状态变量。按以下方式更新您的代码:
string status = "Healthy"; Console.WriteLine($"Start: {status}"); SetHealth(false); Console.WriteLine($"End: {status}"); void SetHealth(bool isHealthy) { status = (isHealthy ? "Healthy" : "Unhealthy"); Console.WriteLine($"Middle: {status}"); }在此代码中,将使用新的字符串值覆盖全局
status变量。保存并运行代码以观察以下输出:
Start: Healthy Middle: Unhealthy End: Unhealthy现在,已更新的字符串已捕获并正确存储。
回顾
下面介绍了到目前为止已了解的值类型和引用类型参数:
- 变量可以归类为值类型和引用类型。
- 值类型直接包含值,引用类型存储值的地址。
- 使用值类型参数的方法创建其自己的值副本。
- 对数组参数执行更改的方法会影响原始输入数组。
- 字符串是不可变引用类型。
- 对字符串参数执行更改的方法不会影响原始字符串。