我在循环浏览一组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....
有什么想法吗?
答案 0 :(得分:1)
每当您拨打.where
并将结果分配给currRow时,您将限制该组。
所以第一行
currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);
将限制所有t&lt; 10.然后再打电话
xValue = 20;
currRow = currRow.Where(yyy => (int)yyy.Attribute("t") < xValue);
你会得到完全相同的结果,因为所有元素由于第一次调用Where和后续赋值给currRow,因此currRow的值小于 10 / p>
你可以这样做
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
}
评论后编辑
使用枚举器时评估的位置
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()
。
答案 1 :(得分: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;
答案 2 :(得分:0)
currRow.Where(...)
将创建一个将在使用时执行的查询 如果您想直接得到结果(并且省略任何引用/查询),请将其转换为列表。
currRow.Where(...).ToList()
你应该这样做的原因是你在where语句中使用的值在查询中不被视为常量,而是对你使用的变量的引用。如果更改变量,则可能会更改查询的结果
如果您调用.ToList()
,则会使用该时刻的变量值执行查询。结果被收集并且是“永久的”,使得当查询中使用的变量的值发生变化时,创建结果的查询将不再影响结果。
答案 3 :(得分: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
。
答案 4 :(得分:0)
目前我的机器上没有VS进行测试,但可能是由于延迟加载。
在LINQ表达式中使用xValue
时,它通过引用而不是值传递。这意味着在枚举LINQ表达式之前,无论何时更改xValue
,您都会无意中更改LINQ表达式。
这篇文章(Are values in LINQ expressions passed by reference?)似乎支持我的理论。尝试将select语句更改为以下内容,它可能会为您提供您期望的行为:
currRow = currRow.Where( yyy => ( int ) yyy.Attribute( "t" ) < xValue ).Select( x => x );