我正在尝试做我认为简单的事情,但我怀疑我只是太难以知道我可能做错了什么。我有一个LINQ查询返回:
IQueryable<CWords> Result
CWords是我定义如下的类:
public class CWords
{
public CWords(){}
public string _column1{ get; set; }
public float _column2{ get; set; }
public void fixData(){}
}
在我的代码中,我试图修改Result的每个成员的_column2字段。我试过了:
foreach (CWords item in Result)
{
item.fixData();
}
但当然没有用。 item不在适当的范围内,因此我在fixData中所做的任何更改都没有在Result中进行。
由于你无法索引到IQueryable,我的解决方法是执行以下操作:
var items = goodWords.ToList();
for (int i = 0; i < items.Count(); i++ )
{
items[i].fixData();
}
这是正确的方法吗?
答案 0 :(得分:16)
Brandon,这是使用LINQ时的一个正常错误。请注意,从LINQ返回的IQueryable实际上并不包含您的项目,这就是您无法将其编入索引的原因。当您实际请求项目时,它只有足够的信息来执行查询。这称为“deferred execution”,因为查询不会在您select
时执行,但稍后会在您枚举结果时执行。您可以搜索“linq延迟执行”并找到许多人试图解释它是如何工作的。
执行foreach
时,查询会运行,您正在按照预期在每个项目上调用fixData()。但是,当您再次访问IQueryable时,您将再次执行查询,并且(取决于您使用的LINQ提供程序),您可能会再次引入原始未修改的项目。
通过调用IQueryable上的ToList(),您将创建一个包含查询所有结果的内存列表。您现在可以索引到此列表并访问它,而无需再次执行查询。如果您可以将所有项目都放在内存中(小结果集),那么使用ToList()可以为您提供良好的解决方案。
@PaulG,你是对的,他可以使用foreach
而不是for
,但他应该保存对列表的引用,否则他就在他开始的地方(使用IQueryable)。
var items = goodWords.ToList();
foreach (var item in items)
{
item.fixData();
}
答案 1 :(得分:0)
我相信你的好词是IQueryable<CWords>
类型?
为什么不喜欢这个?
foreach (CWords item in goodWords.ToList())
{
item.fixData();
}