C#对象赋值出现的诡异问题,或许你也遇到过,有待你的解决

前言:今天在代码中,又出现了这个问题,就是对象赋值给一个新的对象时,然后更改新对象中的属性,就会把老对象的值也更改,以前也遇到这个问题,只是没有深究,今天刚好又遇到了此问题,我决定写下来,和大家一起分享,也同样希望大家给出更加合理的解决方案,和原理。

通过这个简单的例子引出我所出现的问题:

1 int j;
2 j = 1;
3 
4 int k;
5 k = j;
6 
7 k = 2;
8 
9 Console.WriteLine(string.Format("i={0},k={1}", j, k));

代码很简单,输出的结果也很容易看出来,结果当然输入的是:i=1,k=2

这样的输出结果当然无需置疑,那么我们现在按照这个逻辑进入下面的代码,结果除非人的意料。

首先是一个实体对象类:

namespace ConsoleApplication
{
    /// <summary>
    /// 订单
    /// </summary>
    public class OrderInfo
    {
        public OrderInfo()
        {
            this.OrderDetaileInfo = new List<OrderDetaileInfo>();
        }

        /// <summary>
        /// 订单号
        /// </summary>
        public string OrderNO { get; set; }

        /// <summary>
        /// 订单总金额
        /// </summary>
        public decimal OrderAmount { get { return this.OrderDetaileInfo == null ? 0 : this.OrderDetaileInfo.Sum(t => t.Total); } }

        /// <summary>
        /// 订单明细
        /// </summary>
        public List<OrderDetaileInfo> OrderDetaileInfo { get; set; }
    }

    /// <summary>
    /// 订单明细
    /// </summary>
    public class OrderDetaileInfo
    {
        /// <summary>
        /// 订单号
        /// </summary>
        public string OrderNO { get; set; }

        /// <summary>
        /// 商品名称
        /// </summary>
        public string ProductName { get; set; }

        /// <summary>
        /// 商品数量
        /// </summary>
        public int Number { get; set; }

        /// <summary>
        /// 商品单价
        /// </summary>
        public decimal Price { get; set; }

        /// <summary>
        /// 总价
        /// </summary>
        public decimal Total { get { return this.Price * this.Number; } }
    }
}
View Code

下面是一个控制台输出代码,这段代码也就是总体来说,就是一个赋值的问题:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             // 订单
 6             var objOrderInfo = new OrderInfo()
 7             {
 8                 OrderNO = "201507310001"
 9             };
10 
11             // 订单明细
12             OrderDetaileInfo objOrderDetaileInfo = null;
13             for (int i = 1; i < 5; i++)
14             {
15                 objOrderDetaileInfo = new OrderDetaileInfo()
16                 {
17                     OrderNO = objOrderInfo.OrderNO,
18                     Number = i,
19                     Price = i * 5,
20                     ProductName = "三星SSD-" + i
21                 };
22                 objOrderInfo.OrderDetaileInfo.Add(objOrderDetaileInfo);
23             }
24             string str = null;
25             Console.WriteLine("-------------------首次循环OrderDetaileInfo开始--------------------
");
26             objOrderInfo.OrderDetaileInfo.ForEach(t =>
27             {
28                 str = string.Format("订单号:{0}
商品名称:{1}
数量:{2}
单价:{3}
总计:{4}
",
29                     t.OrderNO, t.ProductName, t.Number, t.Price.ToString("C"), t.Total);
30                 Console.WriteLine(str);
31             });
32             Console.WriteLine("订单总金额:" + objOrderInfo.OrderAmount.ToString("C"));
33             Console.WriteLine("-------------------首次循环OrderDetaileInfo结束--------------------");
34 
35             OrderInfo objOrderInfo2 = new OrderInfo()
36             {
37                 OrderNO = "201507310002"
38             };
39             OrderDetaileInfo objOrderDetaileInfo2 = null;
40             int num = 5;
41             foreach (var item in objOrderInfo.OrderDetaileInfo)
42             {
43                 objOrderDetaileInfo2 = new OrderDetaileInfo();
44                 objOrderDetaileInfo2 = item;
45                 objOrderDetaileInfo2.OrderNO = objOrderInfo2.OrderNO;
46                 objOrderDetaileInfo2.Number = num;
47                 num++;
48                 objOrderInfo2.OrderDetaileInfo.Add(objOrderDetaileInfo2);
49             }
50             Console.WriteLine("-------------------重新把OrderDetaileInfo赋值给OrderDetaileInfo2开始---------
");
51             objOrderInfo2.OrderDetaileInfo.ForEach(t =>
52             {
53                 str = string.Format("订单号:{0}
商品名称:{1}
数量:{2}
单价:{3}
总计:{4}
",
54                     t.OrderNO, t.ProductName, t.Number, t.Price.ToString("C"), t.Total);
55                 Console.WriteLine(str);
56             });
57             Console.WriteLine("订单总金额:" + objOrderInfo2.OrderAmount.ToString("C"));
58             Console.WriteLine("-------------------重新把OrderDetaileInfo赋值给OrderDetaileInfo2结束---------");
59 
60             // 当把OrderDetaileInfo赋值给OrderDetaileInfo2后,竟然把OrderDetaileInfo对象变为了OrderDetaileInfo2
61 
62             Console.WriteLine("-------------------再次循环OrderDetaileInfo开始--------------------
");
63             objOrderInfo.OrderDetaileInfo.ForEach(t =>
64             {
65                 str = string.Format("订单号:{0}
商品名称:{1}
数量:{2}
单价:{3}
总计:{4}
",
66                     t.OrderNO, t.ProductName, t.Number, t.Price.ToString("C"), t.Total);
67                 Console.WriteLine(str);
68             });
69             Console.WriteLine("订单总金额:" + objOrderInfo.OrderAmount.ToString("C"));
70             Console.WriteLine("-------------------再次循环OrderDetaileInfo结束--------------------");
71 
72             Console.ReadLine();
73         }
74     }

  

这段代码不难看懂,第一次输出的是订单信息,第二次输出的是把第一次的订单明细赋值给第二次订单的明细,然后改变第二次订单明细是商品的数量(看红色代码),第三次输出的是第一次的订单信息,按照前面j和k的代码,第三次输出的应该和第一次输出的结果一值,BUT,看图:

第一次输出的结果:

第二次输出的结果:

第三次的输出结果(按照J,K的例子,第三次的和第一次的应该一样,可惜啊)LOOK

可惜第三次并不是和第一次一样,而是和第二次输出的订单明细一样。

没办法只能把红色的代码改成这样,才能正确

           foreach (var item in objOrderInfo.OrderDetaileInfo)
            {
                objOrderDetaileInfo2 = new OrderDetaileInfo();
                //objOrderDetaileInfo2 = item;
                objOrderDetaileInfo2.OrderNO = objOrderInfo2.OrderNO;
                objOrderDetaileInfo2.ProductName = item.ProductName;
                objOrderDetaileInfo2.Price = item.Price;
                objOrderDetaileInfo2.Number = num;
                num++;
                objOrderInfo2.OrderDetaileInfo.Add(objOrderDetaileInfo2);
            }

具体解决办法只能这样,不知道哪位大牛更改帮忙讲解一下,或者有更好的解决办法,因为字段多了,一个一个赋值太麻烦。 

随便把DEMO传上来,供大家测试,下载地址

解决方案看:#16楼 #18楼 #27楼,多谢大家的帮助

原文地址:https://www.cnblogs.com/luxianai/p/net_assignment.html