一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

C#将老对象赋值新对象时更改老对象的问题解决

时间:2015-07-31 编辑:简简单单 来源:一聚教程网

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

int j;
j = 1;
int k;
k = j;
k = 2;
Console.WriteLine(string.Format("i={0},k={1}", j, k));



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

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

首先是一个实体对象类:

namespace ConsoleApplication
{
    /// 
    /// 订单
    /// 
    public class OrderInfo
    {
        public OrderInfo()
        {
            this.OrderDetaileInfo = new List();
        }
        /// 
        /// 订单号
        /// 
        public string OrderNO { get; set; }
        /// 
        /// 订单总金额
        /// 
        public decimal OrderAmount { get { return this.OrderDetaileInfo == null ? 0 : this.OrderDetaileInfo.Sum(t => t.Total); } }
        /// 
        /// 订单明细
        /// 
        public List OrderDetaileInfo { get; set; }
    }
    /// 
    /// 订单明细
    /// 
    public class OrderDetaileInfo
    {
        /// 
        /// 订单号
        /// 
        public string OrderNO { get; set; }
        /// 
        /// 商品名称
        /// 
        public string ProductName { get; set; }
        /// 
        /// 商品数量
        /// 
        public int Number { get; set; }
        /// 
        /// 商品单价
        /// 
        public decimal Price { get; set; }
        /// 
        /// 总价
        /// 
        public decimal Total { get { return this.Price * this.Number; } }
    }
}



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

class Program
{
    static void Main(string[] args)
    {
        // 订单
        var objOrderInfo = new OrderInfo()
        {
            OrderNO = "201507310001"
        };
        // 订单明细
        OrderDetaileInfo objOrderDetaileInfo = null;
        for (int i = 1; i < 5; i++)
        {
            objOrderDetaileInfo = new OrderDetaileInfo()
            {
                OrderNO = objOrderInfo.OrderNO,
                Number = i,
                Price = i * 5,
                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 = "201507310002"
        };
        OrderDetaileInfo objOrderDetaileInfo2 = null;
        int num = 5;
        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);
}



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




C#利用反射给对象赋值

我们如果想利用凡是给一个对象属性赋值可以通过PropertyInfo.SetValue()方式进行赋值,但要注意值的类型要与属性保持一致,例如:

var property = obj.GetType().GetProperty(“PropertyName”);//此时可以使用GetProperty获取属性数组,循环进行赋值。

该属性类型是已知基本类型可以直接将变量传入, 例如:string

var value=”wangheng.org”;

property.SetValue(obj,value,null);

这里需要注意value值的类型必须和属性类型一致,否则会抛出TargetException异常。

如果原值是其他类型。例如:目标类型为int,值为string

string value=”100″;

property.SetValue(obj,int.TryParse(value),null);//类型转换。

上面几种都比较容易处理,但是如果该属性类型是未知非泛型类型,例如 int?

var value=”100″;

property.SetValue(obj,Convert.ChangeType(value, property.PropertyType), null);//类型转换。这时简单调用 ChangeType()方法,类型会报错。

想解决这个问题,需要首先把属性值类型转成基本类型,然后进行转换。如下:


if (!property.PropertyType.IsGenericType){//非泛型property.SetValue(obj, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, property.PropertyType), null);}else{//泛型Nullable<>Type genericTypeDefinition = property.PropertyType.GetGenericTypeDefinition();if (genericTypeDefinition == typeof(Nullable<>)){property.SetValue(obj, string.IsNullOrEmpty(value) ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(property.PropertyType)), null);}}

这样,在使用Convert.ChangeType()转换可空类型时,就不会报错了。

热门栏目