[英]Object passed as parameter to another class, by value or reference?
在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#中傳遞 - “對象”不是語言中的值。 該語言中唯一的類型是基本類型,結構類型等和引用類型 。 沒有“對象類型”。
Object
, MyClass
等類型是引用類型。 它們的值是“引用” - 指向對象的指針。 對象只能通過引用來操作 - 當你對它們進行new
操作時,你會獲得一個引用,即.
操作員操作參考; 因為沒有對象類型,所以無法獲得其值為“是”的變量。
所有類型(包括引用類型)都可以通過值或引用傳遞。 如果參數具有ref
或out
類的關鍵字,則通過引用傳遞參數。 SetObject
方法的obj
參數(具有引用類型)沒有這樣的關鍵字,因此它通過值傳遞 - 引用按值傳遞。
無論在同一類或另一類的方法中,對象都將通過引用傳遞。 以下是相同示例代碼的修改版本,以幫助您理解。 該值將更改為“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();
}
}
}
假設someTestObj
是一個class
而不是struct
,則該對象通過引用傳遞,這意味着obj
和someTestObj
引用同一個對象。 例如,在一個中更改name
將在另一個中更改它。 但是,與使用ref
關鍵字傳遞它不同,設置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
}
如果你需要復制對象請參考對象克隆,因為對象是通過引用傳遞的,這對性能有好處,對象創建很昂貴。
這篇文章可以參考: 深度克隆對象
通常,“對象”是類的實例,它是在存儲器中創建的類的“圖像”/“指紋”(通過New關鍵字)。
對象類型的變量指的是這個內存位置,也就是說,它本質上包含內存中的地址。
因此,對象類型的參數將引用/“鏈接”傳遞給對象,而不是整個對象的副本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.