对象作为参数传递给另一个类,通过值还是引用?
Posted
技术标签:
【中文标题】对象作为参数传递给另一个类,通过值还是引用?【英文标题】:Object passed as parameter to another class, by value or reference? 【发布时间】:2012-10-11 10:45:46 【问题描述】:在 C# 中,我知道默认情况下,传递给函数的任何参数都是通过复制的,也就是说,在函数内部,存在参数的本地副本。但是,当一个对象作为参数传递给另一个类时呢?
像下面这样的场景是通过引用传递还是通过值传递:
class MyClass
private Object localObj;
public void SetObject(Object obj)
localObj = obj;
void Main()
Object someTestObj = new Object();
someTestObj.name = "My Name";
MyClass cls = New MyClass();
cls.SetObject(someTesetObj);
在这种情况下,类变量localObj
是否与在Main
驱动程序类中创建的someTestObj
具有相同的副本?或者这两个变量会指向不同的对象实例吗?
【问题讨论】:
“在 C# 中,我知道默认情况下,传递给函数的任何参数都将通过复制”,反之亦然。只有传递给函数的结构才会在函数范围内复制。对象总是通过引用,这意味着内存中只有一个版本,并且每个变量都指向它。 【参考方案1】:“对象”永远不会在 C# 中传递——“对象”不是语言中的值。语言中唯一的类型是原始类型、结构类型等和引用类型。没有“对象类型”。
Object
、MyClass
等类型是引用类型。它们的值是“引用”——指向对象的指针。对象只能通过引用来操作——当你对它们执行new
时,你会得到一个引用,.
操作符对一个引用进行操作;等等。因为没有对象类型,所以无法获取其值“是”对象的变量。
所有类型,包括引用类型,都可以通过值或引用传递。如果参数具有 ref
或 out
之类的关键字,则通过引用传递参数。 SetObject
方法的obj
参数(属于引用类型)没有这样的关键字,所以是按值传递——引用是按值传递的。
【讨论】:
什么?错了,最后一行没有意义。对象总是通过引用(句点)传递。 @States: 不,“对象”不是 C# 中的值,不能“通过”。struct
的实例不是对象吗?这些是按值传递的
是的,结构是值类型,对象是引用类型。就那么简单。如果您想了解更多关于何时适用的信息,有很多关于该主题的文章,Microsoft Docs 中的这篇文章就是一个很好的例子。 docs.microsoft.com/en-us/dotnet/standard/design-guidelines/…【参考方案2】:
对象将通过引用传递,与同一类或另一个类的方法无关。这是相同示例代码的修改版本,以帮助您理解。该值将更改为“xyz”。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
public class Employee
public string Name get; set;
public class MyClass
public Employee EmpObj;
public void SetObject(Employee obj)
EmpObj = obj;
public class Program
static void Main(string[] args)
Employee someTestObj = new Employee();
someTestObj.Name = "ABC";
MyClass cls = new MyClass();
cls.SetObject(someTestObj);
Console.WriteLine("Changing Emp Name To xyz");
someTestObj.Name = "xyz";
Console.WriteLine("Accessing Assigned Emp Name");
Console.WriteLine(cls.EmpObj.Name);
Console.ReadLine();
【讨论】:
对象不是通过引用传递的。引用是按值传递的。这是一个很大的区别,重要的是要清楚这一点,IMOI。 默认情况下,对象是通过值而不是通过引用传递的,我们使用(ref object)通过引用传递对象【参考方案3】:我发现其他示例不清楚,所以我做了自己的测试,确认类实例是通过引用传递的,因此对类执行的此类操作将影响源实例。
换句话说,我的 Increment 方法每次调用时都会修改它的参数 myClass。
class Program
static void Main(string[] args)
MyClass myClass = new MyClass();
Console.WriteLine(myClass.Value); // Displays 1
Increment(myClass);
Console.WriteLine(myClass.Value); // Displays 2
Increment(myClass);
Console.WriteLine(myClass.Value); // Displays 3
Increment(myClass);
Console.WriteLine(myClass.Value); // Displays 4
Console.WriteLine("Hit Enter to exit.");
Console.ReadLine();
public static void Increment(MyClass myClassRef)
myClassRef.Value++;
public class MyClass
public int Value get;set;
public MyClass()
Value = 1;
【讨论】:
【参考方案4】:假设someTestObj
是class
而不是struct
,则对象通过引用传递,这意味着obj
和someTestObj
都引用同一个对象。例如。在其中一个中更改name
将在另一个中更改它。但是,与使用ref
keyword 传递它不同,设置obj = somethingElse
不会改变someTestObj
。
【讨论】:
【参考方案5】:如果作为值类型传递一个对象,那么在方法内部对对象成员所做的更改也会在方法外部受到影响。 但是如果对象本身被设置为另一个对象或重新初始化,那么它不会反映在方法之外。所以我会说对象作为一个整体仅作为 Valuetype 传递,但对象成员仍然是引用类型。
private void button1_Click(object sender, EventArgs e)
Class1 objc ;
objc = new Class1();
objc.empName = "name1";
checkobj(objc);
MessageBox.Show(objc.empName); //propert value changed; but object itself did not change
private void checkobj (Class1 objc)
objc.empName = "name 2";
Class1 objD = new Class1();
objD.empName ="name 3";
objc = objD ;
MessageBox.Show(objc.empName); //name 3
【讨论】:
【参考方案6】:如果需要复制对象请参考对象克隆,因为对象是通过引用传递的,顺便提一下性能好,对象创建成本高。
这里有文章可以参考:Deep cloning objects
【讨论】:
【参考方案7】:通常,“对象”是类的实例,它是在内存中创建的类的“图像”/“指纹”(通过 New 关键字)。 对象类型的变量指的是这个内存位置,也就是它本质上包含了内存中的地址。 因此,对象类型的参数将引用/“链接”传递给对象,而不是整个对象的副本。
【讨论】:
以上是关于对象作为参数传递给另一个类,通过值还是引用?的主要内容,如果未能解决你的问题,请参考以下文章
如何将数组的值作为第二个参数传递给 awk 的 split 函数?