自定义包含TakeWhile(),有更好的方法吗?

时间:2010-06-23 03:00:47

标签: c# linq refactoring

我编写了一个自定义LINQ扩展方法,它将TakeWhile()方法扩展为包含,而不是在谓词为false时将其排除。

        public static IEnumerable<T> TakeWhile<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool inclusive)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            if (!inclusive)
                return source.TakeWhile(predicate);

            var totalCount = source.Count();
            var count = source.TakeWhile(predicate).Count();

            if (count == totalCount)
                return source;
            else
                return source.Take(count + 1);
        }

虽然这有效,但我确信有更好的方法。我很确定这在延迟执行/加载方面不起作用。

ThrowIfNull()ArgumentNullException检查的扩展方法

社区可以提供一些提示或重写吗? :)

2 个答案:

答案 0 :(得分:12)

你是对的;这对延迟执行不友好(调用Count需要完整枚举源代码。)

然而,你可以这样做:

public static IEnumerable<T> TakeWhile<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool inclusive)
{
    foreach(T item in source)
    {
        if(predicate(item)) 
        {
            yield return item;
        }
        else
        {
            if(inclusive) yield return item;

            yield break;
        }
    }
} 

答案 1 :(得分:0)

直接回答问题。我想展示如何使用SkipWhile模拟包含性的TakeWhile逻辑。

IEnumerable<string> list = new List<string> { "1", "2", "3", "4", "5" };
var result = list
    .Reverse()
    .SkipWhile(item => item != "3")
    .Reverse();
// result will be {"1", "2", "3"}

但是请注意,以这种方式执行效率会较低,因为在这种情况下,list实际上必须反转两次。因此,请确保性能不会成为问题。