0

我在循环一组XElements. 这种行为不是我所期望的。

我的代码的简短重写版本,因此您可以轻松解决我的问题(C# 中的控制台应用程序)

IEnumerable<XElement> q = from c in xml.Descendants(aw + "wd") 
                          where (....) 
                          select c;    
...

//--------------------------------------------------------------------    
IEnumerable<XElement> currRow = q.OrderBy(yyy => (int)yyy.Attribute("t"));

int xValue = 10;

currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);
xValue = 20; 
//Here, the currRow gets a new value automatically. I don't want this!


//--------------------------------------------------------------------
//This is want i want to acheive: 

IEnumerable<XElement> currRow = q.OrderBy(yyy => (int)yyy.Attribute("t")); 

int xValue = 10;

currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);
//do somthing with currRow

xValue = 20; 
currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);
//do somthing else with currRow

xValue = 30; 
currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);
// etc....

有任何想法吗?

4

5 回答 5

1

每次您调用.where并将结果分配给 currRow 时,您都在限制集合。

所以第一行

 currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);

将限制为 t < 10 的所有元素。然后调用

 xValue = 20;
 currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);

你会得到完全相同的结果,因为我 currRow 的所有元素的 t 值都小于10,因为第一次调用 Where 并随后分配给 currRow

你可以这样做

   const int stepSize = 10;
   var iterations = 3
    for(var i = 0;i<iterations;++i){
         var curr = currRow.Where(yyy => (int)YYY.Attribute("t") >= i * stepSize 
                                       && (int)YYY.Attribute("t") < (i+1) * stepSize);
         //do sometihng with curr
    }

评论后编辑

使用枚举器时评估 where

xValue = 10;
currRow = currRow.Where(yyy => (int)YYY.Attribute("t") > xValue);

foreach(var elem in currRow){
    //this iterates all elements with t < 10;
}

xValue = 20; 
foreach(var elem in currRow){ //notice that currRow hasn't been reassigned
    //this iterates all elements with t < 20;
}

您必须选择避免这种行为,这是设计使然

您可以避免重新分配 xValue,也可以像这样执行查询

var list = currRow.Where(yyy => (int)YYY.Attribute("t") > xValue).ToList();

注意.ToList()到底。

于 2012-11-01T10:26:11.383 回答
0
IEnumerable<XElement> currRow = q.OrderBy(yyy => (int)yyy.Attribute("t")); 

int xValue = 10;    

var abc = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);
//Do something with abc , abc is IEnumerable<XElement> list;
于 2012-11-01T10:06:18.060 回答
0
currRow.Where(...)

将创建一个在使用时将执行的查询。
如果您希望直接获得结果(并省略任何要搞砸的引用/查询)将其转换为列表。

currRow.Where(...).ToList()

您应该这样做的原因是您在 where 语句中使用的值在查询中不被视为常量,而是对您使用的变量的引用。如果您更改变量,您可能会更改查询的结果。
如果您调用.ToList()查询,则使用该时刻的变量值执行查询。结果被收集并且是“永久的”,这样当查询中使用的变量的值发生变化时,为创建结果而进行的查询将不再影响结果。

于 2012-11-01T10:06:39.230 回答
0

看起来你xValue被捕获到 where 语句的 lambda 表达式中。为什么不简单地提供恒定值?

currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < 20);
//do somthing with currRow
currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < 10);
//do somthing with currRow

也不要从最小过滤值开始< 10。当您将结果分配给currRow变量时,其他过滤器将不起作用,因为结果已经小于20和小于30

于 2012-11-01T10:10:26.650 回答
0

我的机器上目前没有 VS 进行测试,但这可能是由于延迟加载。

当您xValue在 LINQ 表达式中使用它时,它是通过引用而不是按值传递的。这意味着,在您枚举 LINQ 表达式之前,无论何时更改,xValue您都会在不知不觉中更改 LINQ 表达式。

这篇文章(LINQ 表达式中的值是否通过引用传递?)似乎支持我的理论。尝试将您的选择语句更改为以下内容,它可能会给您带来您期望的行为:

currRow = currRow.Where( yyy => ( int ) yyy.Attribute( "t" ) < xValue ).Select( x => x );
于 2012-11-01T11:44:22.587 回答