2009-08-21 41 views
0

我在尝试填充GridView时遇到了一个行为,我无法理解。考虑下面的代码:修改其他对象时发生变化的对象的变量

DataTable table = GetStockMovement((int)ViewState[MOVEMENT_ID], false); 
MovedProducts = from DataRow row in table.Rows 
        select new Product() 
        { 
         ProductId = (int)row["ProductId"], 
         ProductNo = row["ProductNo"].ToString(), 
         Name = row["ProductName"].ToString(), 
         Quantity = OriginalProducts.ToList().Find(p => p.ProductId == (int)row["ProductId"]).Quantity, 
         QuantityDiff = (int)row["Change"]                 
        }; 

foreach (Product product in MovedProducts) 
{ 
    Console.WriteLine(product.ProductId + ": " + product.Quantity); 
} 
Console.WriteLine(); 
foreach (Product product in OriginalProducts) 
{ 
    product.Quantity -= 1000; 
} 


foreach (Product product in MovedProducts) 
{ 
    Console.WriteLine(product.ProductId + ": " + product.Quantity); 
} 

这样做的输出是这样的:

1: 10 
2: 4 

1: -990 
2: -996 

Product.Quantity是int MovedProducts和OriginalProducts是存储在ViewState中IEnumerables。

当我在OriginalProducts中更改时,为什么MovedProducts中的产品发生更改?他们不是存储在不同地方的两个完全不同的对象吗?

如果我而不是使用LINQ表达:

List<FPRSProduct> completedProducts = new List<FPRSProduct>(); 
foreach (DataRow row in table.Rows) 
{ 
    Product tmp = new Product(); 
    tmp.ProductId = (int)row["ProductId"]; 
    tmp.ProductNo = row["ProductNo"].ToString(); 
    tmp.Name = row["ProductName"].ToString(); 
    tmp.Quantity = OriginalProducts.ToList().Find(p => p.ProductId == (int)row["ProductId"]).Quantity; 
    tmp.QuantityDiff = (int)row["Change"];                 
    completedProducts.Add(tmp); 
} 

一切工作,因为我预料到,这是我之前和改变OriginalProducts的数量后得到相同的号码。

回答

2

LINQ利用我们所说的延期执行。当你写出一个linq查询时,你实际上并没有执行查询定义的任务......你只是简单地定义它。你的查询定义的行为在使用时执行......在你的情况下,在两个foreach语句中执行。对于每个foreach,查询都是TWICE执行的,所以即使数据被复制......它在两个不同的时间点从源复制两次。围绕您的MovedProducts的第二个foreach检索您的OriginalProducts中更新的数据,因为执行查询被推迟到实际执行第二个foreach。

注意代码的链接查询“选择新的”条款在本重点线:

Quantity = OriginalProducts.ToList().Find(p => p.ProductId == (int)row["ProductId"]).Quantity, 

既然你更新的第一和第二的foreach之间OriginalProducts,即使你正在创建一个distinc,产品对象列表...由于查询的处理被推迟,因此您对每个产品的上述行执行两次。第一次是foreach,第二次是foreach。

相关问题