LINQ查询Bool + String对列表。没有foreach如何连接字符串?

时间:2011-12-20 00:33:46

标签: c# string linq foreach concatenation

对对象的LINQ查询有疑问......

我有这个过滤器描述,我希望保密,并且在代码中的给定检查点,我设置了一些活动的标志。在处理结束时,我想过滤活动标志。

如果有任何标志处于活动状态,我想将它们写入控制台。 (我希望所有标记的检查点都在一个字符串中,所以我可以更改代码以便稍后抛出异常)。

这是代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;

namespace checkpoints
{
    public class Program
    {
        public static void Main(string[] args)
        {            
            var filters = new Filters().FilterList;

            filters[0].flag = true;
            filters[2].flag = true;

            var query = filters.Where(f => f.flag).Select(f => f.desc); 
            Console.WriteLine("Filter points active: ");
            string fpoints = System.String.Empty;

            foreach(string fp in query)
                { fpoints = fpoints + fp + System.Environment.NewLine; }

            Console.WriteLine(fpoints);
        }
    }
    public class Filters
    {        
        public List<Filter> FilterList = new List<Filter>{};

        public Filters()
        {
           foreach(var def in Filters.def_desc)               
               { this.FilterList.Add(new Filter(false, def)); }
        }

        private readonly static string[] def_desc = new string[3]
        { "Filter AX2123: Failed file write.", 
          "Filter XVB231: Failed table load.", 
          "Filter FZD358: Transaction halted." };

        public class Filter
        {
            public bool flag;
            public readonly string desc;       

            public Filter(bool flag, string desc)
            {
                this.flag = flag;
                this.desc = desc;
            }
        }            

    }
}

有效。我的问题是需要为LINQ查询结果(我猜是IEnumerable<Filter>)运行一个for,以便提取字符串。如果我已经运行了一个查询(即遍布代码)为什么我需要“再次运行”?看起来它很可怕并且不是很优雅......有什么想法吗?

6 个答案:

答案 0 :(得分:2)

var query = filters.Where(f => f.flag).Select(f => f.desc);的调用不会运行查询。调用链返回的IEnumerable<Filter>不会收集Filter个对象,直到您在foreach循环中枚举返回结果为止。

这有利有弊。优点是,在不需要查询结果的情况下,可以节省评估查询所需的所有CPU时间。缺点是如果需要多次枚举结果,系统第二次需要再次重新计算结果。解决上一个问题的方法是立即枚举您的查询结果,并将它们放入数组或列表中,如下所示:

var queryResults = filters.Where(f => f.flag).Select(f => f.desc).ToList();

答案 1 :(得分:2)

由于dasblinkenlight和Daev已经提到了延迟执行部分,我认为你有兴趣知道你可以通过替换

来加入字符串而不用foreach
foreach(string fp in query)
{ fpoints = fpoints + fp + System.Environment.NewLine; }

string.Join(Environment.NewLine, query)

答案 2 :(得分:2)

string fpoint=query.Aggregate((c, c1) => c + System.Environment.NewLine+ c1 );

答案 3 :(得分:1)

您的query变量是表达式,在枚举之前(在您的情况下由foreach进行枚举)不会进行评估。如果您使用调试器检查query,则不会将其内容视为Filter的集合而是查询以获取结果。这被称为“延迟执行”,在Blog Post中很好地涵盖了(虽然它的Linq-SQL适用相同的主体)。

答案 4 :(得分:1)

如果你想摆脱你的foreach,那么你可以尝试一些傻瓜。

string.Join(Environment.NewLine, query.ToArray());

如果我没有仔细阅读你的问题,请道歉:)

答案 5 :(得分:0)

你所追求的是名为aggregate的LINQ函数。它会将列表项连在一起组成一个输出。

快速谷歌显示此stackoverflow帖子显示如何使用聚合函数:Linq Aggregate function

一个简单的例子就是在这里使用函数:http://blueonionsoftware.com/blog.aspx?p=509fa3f8-c125-4e61-9227-8ca4c4e29210。这个例子使用逗号,你可以改用新行。