首页 > 解决方案 > 对象得到更新,它作为参数传递给 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对象也得到更新(据我说不应该)。为什么以及如何发生这种情况?

标签: c#

解决方案


这里要理解的基本内容是,当我们将引用类型的对象传递给方法时,引用是按值传递的。在您的代码中,没有创建新对象的位置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;
    }
}

现在我们有一个新对象,我们设置它的状态。现在updatedOrderandorderDetails都引用了不同的对象,改变一个对象的状态不会导致另一个对象的改变。

请注意,这适用于 c# 中的引用类型,即类和接口对象,而不适用于值类型lile intlongstruct


推荐阅读