张赐荣——一位视障程序员。
赐荣小站: www.prc.cx

張賜榮

张赐荣的技术博客

博客园 首页 新随笔 联系 订阅 管理

C# 方法参数传递 struc 和 class 的区别

下面的示例演示了将结构(struct)传递给方法与将类实例(class)传递给方法之间的区别。
在本例中,两个参数(结构和类实例)都是按值传递的,并且这两种方法都会更改参数字段的值。然而,由于传递结构和传递类实例之间的差异,这两种方法的结果是不同的。
由于结构是值类型,当结构按值传递给方法时,该方法接收结构参数的副本并对其进行操作。
该方法无法访问调用方法中的原始结构,因此无法对其进行任何更改。它只能更改传入的副本。
因为类的实例是引用类型,而不是值类型。
因此,当引用类型按值传递给方法时,该方法会收到对类实例的引用的副本(相当于是指向类的地址)。
也就是说,被调用的方法接收实例地址的副本,而调用的方法保留实例的原始地址。
调用方法中的类实例具有地址,所调用的方法中的参数具有地址副本,且这两个地址引用同一个对象。
因为参数只包含地址的副本,所以被调用的方法不能在调用方法中更改类实例的地址。
但是,被调用的方法可以使用该地址的副本来访问原始地址和地址副本引用的类成员。
如果被调用的方法更改了类成员,则调用方法中的原始类实例也会更改。
下面的示例输出说明了两者之间的区别。
调用ClassTaker方法会改变类实例的willIChange字段的值,因为该方法使用参数中的地址来查找类实例的指定字段。
调用 StructTaker 方法不会更改调用方法中结构的 willIChange 字段,因为该参数的值是结构本身的副本,而不是其地址的副本。
StructTaker 更改了副本,对 StructTaker 的调用完成时,副本就会丢失。

代码

class TheClass
{
public string willIChange;
}
struct TheStruct
{
public string willIChange;
}
class TestClassAndStruct
{
static void ClassTaker(TheClass c)
{
c.willIChange = "Changed";
}
static void StructTaker(TheStruct s)
{
s.willIChange = "Changed";
}
static void Main()
{
TheClass testClass = new TheClass();
TheStruct testStruct = new TheStruct();
testClass.willIChange = "Not Changed";
testStruct.willIChange = "Not Changed";
ClassTaker(testClass);
StructTaker(testStruct);
Console.WriteLine("Class field = {0}", testClass.willIChange);
Console.WriteLine("Struct field = {0}", testStruct.willIChange);
// 在调试模式下保持控制台窗口打开。
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}

/*
输出:
class 字段=已更改
struct 字段=未更改
*/

[本文作者:张赐荣]

posted on 2022-07-13 15:33  张赐荣  阅读(333)  评论(0编辑  收藏  举报

感谢访问张赐荣的技术分享博客!
博客地址:https://cnblogs.com/netlog/
知乎主页:https://www.zhihu.com/people/tzujung-chang
个人网站:https://prc.cx/