[英]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;
}
}
現在我們有一個新對象,我們可以設置它的狀態。 現在updatedOrder
和orderDetails
都是對不同對象的引用,並且改變一個的狀態不會導致改變另一個。
請注意,這適用於 c# 中的引用類型,即類和接口對象,不適用於值類型 lile int
、 long
、 struct
等
來自 docs.microsoft.com:
引用類型的變量不直接包含其數據; 它包含對其數據的引用。 當您按值傳遞引用類型參數時,可以更改屬於被引用對象的數據,例如類成員的值。
您正在將orderDetails
對象的引用傳遞給GenerateOrderID
方法。 所以你在這個方法中修改的對象仍然是同一個對象。 GenerateOrderID
執行更改此對象的狀態。 因此,當您將orderDetails
傳遞給InsertOneAsync
方法時,您傳遞的引用會引用您在GenerateOrderID
中修改的已更改對象。
我猜您在想,當您傳遞orderDetails
,您傳遞的是對象的副本 - 但事實並非如此。 您正在傳遞引用的副本。 所以,如果你分配的東西到order
的方法的參考里面, orderDetails
中WriteOrder
方法引用仍將引用舊的對象。 但是在這里,您正在更改指向的對象的某些字段。
我建議閱讀此內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.