LINQ结果在for循环结束时发生变化 [英] LINQ results change at end of for loop

查看:53
本文介绍了LINQ结果在for循环结束时发生变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当对数据源执行一组LINQ查询时(我使用的是LINQ-to-SQL,但是这里也仅使用 List< string> 对象发生这种情况),我结束了在检查结束时得到了不同的结果.

具体来说,下面的代码试图查找主机名列表中是否存在完全限定域名(FQDN)(并非所有域名都是FQDN或在同一域中,但是主机标识符很重要)对我来说).搜索试图查找是否存在"host-6.domain.local" 或其任何子组件(即"host-6.domain" "host-6" ),但不是.在for循环中,我们得到了预期的结果,但是在for循环完成后,我得到的结果具有列表内容的 all ,在我看来,它正在尝试查找与空字符串匹配的元素.

void MyMethod(){字符串fqdn ="host-6.domain.local";string [] splitFqdn = fqdn.Split('.');List< string>values = new List();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;为(int i = splitFqdn.Length; i> 0; i--){结果=从价值到价值其中value.StartsWith(string.Join(.",splitFqdn.Take(i)))选择值Console.WriteLine(在for循环内,使用" + i +:" + result.Count());}Console.WriteLine();Console.WriteLine(外部循环:" + result.Count());} 

为什么会发生这种情况?在for循环完成后如何获得仍然可以访问的准确结果?

解决方案

您会被LINQ的懒惰执行和关闭所困扰.

创建像这里一样的枚举时...

 结果=从价值到价值其中value.StartsWith(string.Join(.",splitFqdn.Take(i)))选择值 

直到您执行强制其进行评估的操作时,它才会被评估...例如,当您执行 result.count()

然后在循环之外稍后再次评估它时,将使用for循环中存在的i的最后一个值来评估 result.count(),这没有给您想要的东西./p>

尝试对您的枚举执行 .ToList()来强制评估,如下所示.此代码显示了两个值,因此您可以进行比较.

  void MyMethod(){字符串fqdn ="host-6.domain.local";string [] splitFqdn = fqdn.Split('.');List< string>值=新的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;为(int i = splitFqdn.Length; i> 0; i--){queryResult =从价值到价值其中value.StartsWith(string.Join(.",splitFqdn.Take(i)))选择值CorrectResult = queryResult.ToList();Console.WriteLine(在for循环中,使用" + i +:" + queryResult.Count());}Console.WriteLine();Console.WriteLine(循环外的queryResult:" + queryResult.Count());Console.WriteLine(循环外的correctResult:" + correctResult.Count());} 

感谢nlips 指出我尚未完全回答问题...以及为转换为方法语法而道歉,但转换为查询语法将花费更长的时间.

  void MyMethod(){string fqdn = "host-6.domain.local";string[] splitFqdn = fqdn.Split('.');List< string>值=新的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>();为(int i = splitFqdn.Length; i> 0; i--){CorrectResult =更正结果.Union(values.Where(值=>value.StartsWith(string.Join(.",splitFqdn.Take(i))))).ToList();}} 

When performing a set of LINQ queries against a data-source (I'm using LINQ-to-SQL, but it happens here too using just a List<string> object), I end up getting a different result at the end of my checks.

Specifically, the code below is trying to find if a Fully Qualified Domain Name (FQDN) either exists in a list of host names (not all of which will be FQDNs or in the same domain, but the host identifier is what matters to me). The search is trying to find whether "host-6.domain.local" or any of its sub-components exist (i.e, "host-6.domain" or "host-6") in the list, which they do not. While inside the for-loop, we get the results we expect, but as soon as the for loop is finished, I get a result that has all of the contents of the list, which to me sounds like it is trying to find elements that match the empty string.

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());  
}

Why is this happening and how can I get accurate results that I can still access after the for loop is finished?

解决方案

You are getting bitten by LINQ's lazy execution and closure.

When you create an enumerable like you are doing here...

result =  
    from value in values  
    where value.StartsWith(  
        string.Join(".", splitFqdn.Take(i)))  
    select value;  

It doesn't get evaluated until you do something that forces it to get evaluated... for instance when you do result.count()

Then later outside of your loop when you evaluate it again result.count() is evaluated with the last value of i that existed in your for loop which is not giving you what you want.

Try forcing evaluation by doing .ToList() on your enumerable like so... This code shows both values so you can compare.

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());  
}

EDIT: Thanks nlips for pointing out that I hadn't fully answered the question... and apologies for converting to method syntax but it would have taken longer to convert to query syntax.

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();
    }
}

这篇关于LINQ结果在for循环结束时发生变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆