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

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

 int j;
j = ; int k;
k = j; k = ; 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 ? : 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; } }
}
}

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

 class Program
{
static void Main(string[] args)
{
// 订单
var objOrderInfo = new OrderInfo()
{
OrderNO = ""
}; // 订单明细
OrderDetaileInfo objOrderDetaileInfo = null;
for (int i = ; i < ; i++)
{
objOrderDetaileInfo = new OrderDetaileInfo()
{
OrderNO = objOrderInfo.OrderNO,
Number = i,
Price = i * ,
ProductName = "三星SSD-" + i
};
objOrderInfo.OrderDetaileInfo.Add(objOrderDetaileInfo);
}
string str = null;
Console.WriteLine("-------------------首次循环OrderDetaileInfo开始--------------------\n");
objOrderInfo.OrderDetaileInfo.ForEach(t =>
{
str = string.Format("订单号:{0}\n商品名称:{1}\n数量:{2}\n单价:{3}\n总计:{4}\n",
t.OrderNO, t.ProductName, t.Number, t.Price.ToString("C"), t.Total);
Console.WriteLine(str);
});
Console.WriteLine("订单总金额:" + objOrderInfo.OrderAmount.ToString("C"));
Console.WriteLine("-------------------首次循环OrderDetaileInfo结束--------------------"); OrderInfo objOrderInfo2 = new OrderInfo()
{
OrderNO = ""
};
OrderDetaileInfo objOrderDetaileInfo2 = null;
int num = ;
foreach (var item in objOrderInfo.OrderDetaileInfo)
{
objOrderDetaileInfo2 = new OrderDetaileInfo();
objOrderDetaileInfo2 = item;
objOrderDetaileInfo2.OrderNO = objOrderInfo2.OrderNO;
objOrderDetaileInfo2.Number = num;
num++;
objOrderInfo2.OrderDetaileInfo.Add(objOrderDetaileInfo2);
}
Console.WriteLine("-------------------重新把OrderDetaileInfo赋值给OrderDetaileInfo2开始---------\n");
objOrderInfo2.OrderDetaileInfo.ForEach(t =>
{
str = string.Format("订单号:{0}\n商品名称:{1}\n数量:{2}\n单价:{3}\n总计:{4}\n",
t.OrderNO, t.ProductName, t.Number, t.Price.ToString("C"), t.Total);
Console.WriteLine(str);
});
Console.WriteLine("订单总金额:" + objOrderInfo2.OrderAmount.ToString("C"));
Console.WriteLine("-------------------重新把OrderDetaileInfo赋值给OrderDetaileInfo2结束---------"); // 当把OrderDetaileInfo赋值给OrderDetaileInfo2后,竟然把OrderDetaileInfo对象变为了OrderDetaileInfo2 Console.WriteLine("-------------------再次循环OrderDetaileInfo开始--------------------\n");
objOrderInfo.OrderDetaileInfo.ForEach(t =>
{
str = string.Format("订单号:{0}\n商品名称:{1}\n数量:{2}\n单价:{3}\n总计:{4}\n",
t.OrderNO, t.ProductName, t.Number, t.Price.ToString("C"), t.Total);
Console.WriteLine(str);
});
Console.WriteLine("订单总金额:" + objOrderInfo.OrderAmount.ToString("C"));
Console.WriteLine("-------------------再次循环OrderDetaileInfo结束--------------------"); Console.ReadLine();
}
}

这段代码不难看懂,第一次输出的是订单信息,第二次输出的是把第一次的订单明细赋值给第二次订单的明细,然后改变第二次订单明细是商品的数量(看红色代码),第三次输出的是第一次的订单信息,按照前面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楼,多谢大家的帮助

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

  1. C#的对象赋值

    例如 Class A {       int x = 0;       int y = 0; }   public void test() {       A test1 = new A( );   ...

  2. Javascript对象赋值操作

    首先,我们还是举个例子来说明对象赋值操作的问题吧: ps: 本文默认约定log = console.log function A(){} A.prototype.x = 10; var a1 = ne ...

  3. c# 利用反射动态给实体类对象赋值

    转:http://blog.sina.com.cn/s/blog_659a572b0100xp5s.html 例子如下 using System; using System.Collections.G ...

  4. C风格字符串和C++ string 对象赋值操作的性能比较

    <<C++ Primer>> 第四版 Exercise Section 4.3.1 部分Exercise 4.2.9 习题如下: 在自己本机执行如下程序,记录程序执行时间: # ...

  5. 由PHP实现单向链表引发的对象赋值,对象传参,链表操作引发的一系列问题

    2019年2月25日14:21:13 测试版本php 5.4 ,5.6,7.0,7.2 代码请看: https://www.cnblogs.com/zx-admin/p/10373866.html 1 ...

  6. C# 反射给对象赋值遇到的问题——类型转换

    反射给对象赋值遇到的问题——类型转换 给一个对象属性赋值可以通过PropertyInfo.SetValue()方式进行赋值,但要注意值的类型要与属性保持一致.    创建对象实例的两种方法: 1. 1 ...

  7. php中对象赋值问题

    今天遇到一个问题, 一开始拼接的SQL语句,然后想多次使用时发现会被重置,然后想到给重新赋值一次,但是发现这样赋值会出问题,百思不得其解,最后经过搜索,发现PHP中对象赋值给一个变量之类的赋值的其实是 ...

  8. 【java】对象赋值给另一个对象

    对基本数据类型的赋值很简单的.基本类型存储了实际的数值,而并非指向一个对象的引用,所以在赋值的时候,是直接将一个地方的内容复制到另一个地方.对于a=b,修改b后并不会影响到a,这正是我们大多数情况下所 ...

  9. js关闭当前页面和给子页面的对象赋值

    代码如下: function saveData(){ //给父页面的对象赋值 frameElement.api.opener.document.getElementById("userNam ...

随机推荐

  1. WinRAR 自动解压 解压完成后,执行批处理文件

    部分内容参考网页:http://bbs.kafan.cn/thread-1243208-1-1.html WinRAR 的自动解压文件功能使压缩包也能像 Setup 程序那样,双击后显示一个软件许可, ...

  2. Java学习之Java实现CallBack功能

    回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数.而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在 ...

  3. Stream与byte转换

    将 Stream 转成 byte[] /// <summary> /// 将 Stream 转成 byte[] /// </summary> public byte[] Str ...

  4. [原创]反汇编之一:和Taskmgr过不去篇(无厘头版)

    原文链接:和Taskmgr过不去篇(无厘头版) Hook入门级文章,主要想培养一下偶写文章的感觉,老鸟无视…我想看看技术文章能不能无厘头的写,如果效果不错的话,准备更上一层-----用我的原创漫画表达 ...

  5. CeontOS7安装ansible

    安装方法一. 第一步:安装epel rpm -ivh http://mirror.pnl.gov/epel/7/x86_64/e/epel-release-7-5.noarch.rpm 第二步:安装a ...

  6. SQL Server 完成性检查的顺序

    第一步: 默认值 第二步: 违反not null 限制 第三步: 判断check约束 第四步: 对引用表应用foreign key 检查 第五步: 对被引用表做 foreign key 检查 第六步: ...

  7. SQL Server 执行计划重编译的两大情况

    1.与正确性相关的重编译 1.为表或视图添加列,删除列. 2.为表添加约束.默认值.规则,删除约束.默认值.规则. 3.为表或视图添加索引. 4.如果计划用不用索引而这个索引被删除. 5.删除表中的统 ...

  8. 发送邮件java实现

    下面代码可以实现普通qq邮箱发送邮件的功能,可以传附件,但是是固定的附件: 需要两个jar包:mail.jar,activation.jar mail.jar 下载地址: http://java.su ...

  9. J2SE知识点摘记(二十三)

    我们简单介绍一下这个接口: 1.4.3        Comparable 接口 在 java.lang 包中,Comparable 接口适用于一个类有自然顺序的时候.假定对象集合是同一类型,该接口允 ...

  10. arcEngine添加标注(上)

    arcEngine添加标注有3个技术点:1,获得图层的属性字段:2,初始化符号显示控件:3,添加标注. 获得图层的属性字段:   //每个图层都是一个表的图形化显示,ILayer跟ITale可以互相转 ...