簡體   English   中英

通過值或引用將對象作為參數傳遞給另一個類?

[英]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#中傳遞 - “對象”不是語言中的值。 該語言中唯一的類型是基本類型,結構類型等和引用類型 沒有“對象類型”。

ObjectMyClass等類型是引用類型。 它們的值是“引用” - 指向對象的指針。 對象只能通過引用來操作 - 當你對它們進行new操作時,你會獲得一個引用,即. 操作員操作參考; 因為沒有對象類型,所以無法獲得其值為“是”的變量。

所有類型(包括引用類型)都可以通過值或引用傳遞。 如果參數具有refout類的關鍵字,則通過引用傳遞參數。 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 ,則該對象通過引用傳遞,這意味着objsomeTestObj引用同一個對象。 例如,在一個中更改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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM