繁体   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