在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
是否与someTestObj
驱动程序类中创建的Main
具有相同的副本?或者两个变量是否指向不同的对象实例?
无论在同一类或另一类的方法中,对象都将通过引用传递。以下是相同示例代码的修改版本,以帮助您理解。该值将更改为“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();
}
}
}
“对象”永远不会在C#中传递 - “对象”不是语言中的值。该语言中唯一的类型是基本类型,结构类型等和引用类型。没有“对象类型”。
Object
,MyClass
等类型是参考类型。它们的值是“引用” - 指向对象的指针。对象只能通过引用来操作 - 当你对它们执行new
时,你得到一个引用,.
操作符对引用进行操作;因为没有对象类型,所以无法获得其值为“是”的变量。
所有类型(包括引用类型)都可以通过值或引用传递。如果参数具有ref
或out
之类的关键字,则通过引用传递参数。 SetObject
方法的obj
参数(具有引用类型)没有这样的关键字,因此它通过值传递 - 引用按值传递。
假设someTestObj
是class
而不是struct
,则该对象通过引用传递,这意味着obj
和someTestObj
都指向同一个对象。例如。改变name
在一个将改变另一个。但是,与使用ref
keyword传递它不同,设置obj = somethingElse
不会改变someTestObj
。
我发现其他示例不清楚,所以我做了我自己的测试,确认了一个类实例通过引用传递,因此对该类执行的操作将影响源实例。
换句话说,我的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;
}
}
如果作为值类型传递,则对方法内部对象的成员所做的更改也会受到方法外部的影响。但是如果对象本身设置为另一个对象或重新初始化,那么它将不会反映在方法之外。所以我会说对象作为一个整体只作为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
}
如果你需要复制对象请参考对象克隆,因为对象是通过引用传递的,这对性能有好处,对象创建很昂贵。
这篇文章可以参考:Deep cloning objects
通常,“对象”是类的实例,它是在存储器中创建的类的“图像”/“指纹”(通过New关键字)。 对象类型的变量指的是这个内存位置,也就是说,它本质上包含内存中的地址。 因此,对象类型的参数将引用/“链接”传递给对象,而不是整个对象的副本。