当对数据源执行一组LINQ查询(我使用LINQ,但这里也使用List<string>对象)时,我在检查结束时得到了不同的结果。
具体来说,下面的代码试图找出一个完全限定的域名(FQDN)是否存在于主机名列表中(并不是所有这些名称都是FQDN或相同的域,但主机标识符才是我关心的问题)。搜索试图查找列表中是否存在"host-6.domain.local"或其任何子组件(即,"host-6.domain"或"host-6"),而它们并不存在。在for -循环中,我们得到了我们期望的结果,但是,在for循环完成后,我得到了一个包含列表所有内容的结果,在我看来,这似乎是在试图找到与空字符串匹配的元素。
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.add("host-1");
values.add("host-2.domain.local");
values.add("host-3.domain.local");
values.add("host-4");
values.add("host-5.other.local");
IEnumerable<string> queryResult = null;
for (int i = splitFqdn.Length; i > 0; i--)
{
result =
from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value;
Console.WriteLine(
"Inside for loop, take " + i + ": " + result.Count());
}
Console.WriteLine();
Console.WriteLine(
"Outside for loop: " + result.Count());
}为什么会发生这种情况,如何获得在for循环完成后仍然可以访问的准确结果?
发布于 2014-03-20 18:44:02
你被LINQ懒惰的执行和关闭咬死了。
当您创建一个像您在这里所做的可枚举的.
result =
from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value; 它不会被评估直到你做了一些强制它被评估的事情.例如,当您执行result.count()时
然后,在循环之外,当您再次计算它时,result.count()将使用您的for循环中存在的i的最后一个值进行计算,这没有给出您想要的结果。
尝试通过对可枚举的.ToList()执行这样的强制求值。此代码显示这两个值,以便进行比较。
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.add("host-1");
values.add("host-2.domain.local");
values.add("host-3.domain.local");
values.add("host-4");
values.add("host-5.other.local");
IEnumerable<string> queryResult = null;
List<string> correctResult = null;
for (int i = splitFqdn.Length; i > 0; i--)
{
queryResult =
from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value;
correctResult = queryResult.ToList();
Console.WriteLine(
"Inside for loop, take " + i + ": " + queryResult.Count());
}
Console.WriteLine();
Console.WriteLine(
"Outside for loop queryResult: " + queryResult.Count());
Console.WriteLine(
"Outside for loop correctResult: " + correctResult.Count());
}编辑:谢谢指出我没有完全回答这个问题.对于转换为方法语法表示歉意,但是将其转换为查询语法需要更长的时间。
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.Add("host-1");
values.Add("host-2.domain.local");
values.Add("host-3.domain.local");
values.Add("host-4");
values.Add("host-5.other.local");
values.Add("host-5.other.local");
IEnumerable<string> queryResult = null;
List<string> correctResult = new List<string>();
for (int i = splitFqdn.Length; i > 0; i--)
{
correctResult = correctResult
.Union(values.Where(
value => value.StartsWith(string.Join(".", splitFqdn.Take(i)))))
.ToList();
}
}发布于 2014-03-20 19:53:55
对于我的问题,我真的很喜欢凯文的answer,但我不太喜欢在结果上调用.ToList(),因为这将导致从数据库中提取所有匹配的对象(消耗更多内存),而不是执行一个查询,该查询只获得匹配对象的计数(这会稍微快一些,并且不会占用内存来存储对象),因此,使用他的帖子中的信息,我有了这个额外的解决方案,它不需要从数据库中提取所有对象,只运行一个计数查询(在SQL意义上)。
为了避免捕获i (在for -循环结束时成为0 )引起的问题,我只需设置一个临时变量来保存正在搜索的值。
void MyMethod()
{
string fqdn = "host-6.domain.local";
string[] splitFqdn = fqdn.Split('.');
List<string> values = new List<string>();
values.add("host-1");
values.add("host-2.domain.local");
values.add("host-3.domain.local");
values.add("host-4");
values.add("host-5.other.local");
IEnumerable<string> queryResult = null;
for (int i = splitFqdn.Length; i > 0; i--)
{
//taking the line referencing i out of the
//query expression prevents referencing i
//after it is set to 0 outside the for loop
string temp = string.Join(".", splitFqdn.Take(i));
//since temp isn't changed anywhere else, it won't
//get set to an invalid value after the loop exits
result =
from value in values
where value.StartsWith(temp)
select value;
Console.WriteLine(
"Inside for loop, take " + i + ": " + result.Count());
}
Console.WriteLine();
Console.WriteLine(
"Outside for loop: " + result.Count());
}发布于 2014-03-20 18:35:49
我认为在为结果变量赋值时需要调用ToList,如下所示:
result =
(from value in values
where value.StartsWith(
string.Join(".", splitFqdn.Take(i)))
select value).ToList();https://stackoverflow.com/questions/22542052
复制相似问题