簡體   English   中英

對象得到更新,它作為參數傳遞給 c# 中的方法

[英]Object getting updated which is passed as a parameter to a method in c#

我今天在我的應用程序中觀察到了一個奇怪的行為。 我的數據訪問層中有如下方法之一:

public async Task<Order> WriteOrder(Order orderDetails)
{
    try
    {
        Order updatedOrder = GenerateOrderID(orderDetails);
        Task insertOrder = orderCollection.InsertOneAsync(orderDetails);  // updatedOrder was supposed to be passed here.
       // inserts values into Database.        
    }
}

private Order GenerateOrderID(Order order)
{
    try
    {
        order.Id = Guid.NewGuid().ToString();
        order.SubmittedOn = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss");                
        return order;
    }
    catch(Exception ex)
    {            
        throw;
    }
}
public class Order 
{

    [DataMember(Name = "id")]
     public string Id { get; set; }

    [DataMember(Name = "submittedOn")]
    public string SubmittedOn { get; set; }

    // some other Data Memebers

}

說明
WriteOrder方法正在接收orderDetails作為輸入參數,然后我將它傳遞給GeneratedOrderId方法,在那里更新 Id 和其他一些細節並返回訂單對象。 我們在updatedOrder對象中接收對象(我們沒有在任何地方使用)。 然后將orderdetails對象傳遞給InsertOneAsync方法並插入到數據庫中。

一直以來我都沒有注意到它,但我應該將updatedOrder作為參數傳遞給InsertOneAsync方法,而不是orderDetails

但不知何故它正在工作,即 Id 和SubmittedOn詳細信息在數據庫中得到更新。當我調試並看到時, orderDetails對象也得到更新(根據我的說法,這是不應該的)。 為什么以及如何發生這種情況?

這里要理解的基本事情是,當我們將引用類型的對象傳遞給方法時,引用是按值傳遞的。 在您的代碼中,沒有創建Order的新對象的位置。

因此,無論您在何處更改屬性值,都會更新同一對象的狀態。 內存中只有一個對象,並且您有指向相同引用的不同副本。

這意味着在以下方法調用中:

private Order GenerateOrderID(Order order)

order變量持有相同的對象,該對象由調用者端的orderDetails指向。 引用的兩個副本,但指向內存中的同一對象。

如果您在私有方法中創建Order新對象,則方法中的一個小變化將完全改變行為。 然后你會看到傳遞的對象沒有得到更新。 看:

private Order GenerateOrderID(Order order)
{
    try
    {
        order = new Order(); // note this line
        order.Id = Guid.NewGuid().ToString();
        order.SubmittedOn = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss");                
        return order;
    }
    catch(Exception ex)
    {            
        throw;
    }
}

現在我們有一個新對象,我們可以設置它的狀態。 現在updatedOrderorderDetails都是對不同對象的引用,並且改變一個的狀態不會導致改變另一個。

請注意,這適用於 c# 中的引用類型,即類和接口對象,不適用於值類型 lile intlongstruct

來自 docs.microsoft.com:

引用類型的變量不直接包含其數據; 它包含對其數據的引用。 當您按值傳遞引用類型參數時,可以更改屬於被引用對象的數據,例如類成員的值。

您正在將orderDetails對象的引用傳遞給GenerateOrderID方法。 所以你在這個方法中修改的對象仍然是同一個對象。 GenerateOrderID執行更改此對象的狀態。 因此,當您將orderDetails傳遞給InsertOneAsync方法時,您傳遞的引用會引用您在GenerateOrderID中修改的已更改對象。

我猜您在想,當您傳遞orderDetails ,您傳遞的是對象的副本 - 但事實並非如此。 您正在傳遞引用的副本。 所以,如果你分配的東西到order的方法的參考里面, orderDetailsWriteOrder方法引用仍將引用舊的對象。 但是在這里,您正在更改指向的對象的某些字段。

我建議閱讀此內容

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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