Linq 以不同方式处理第一个IEnumerable项的最优雅方式

Linq 以不同方式处理第一个IEnumerable项的最优雅方式,linq,ienumerable,skip,Linq,Ienumerable,Skip,在不必在每次迭代中进行测试的情况下,以不同于其他方式处理第一个IEnumerable项的最优雅方式是什么 在每次迭代中进行一次测试,结果如下所示: // "first item done" flag bool firstDone = false; // items is an IEnumerable<something> foreach (var item in items) { if (!firstDone) { // do this only o

在不必在每次迭代中进行测试的情况下,以不同于其他方式处理第一个IEnumerable项的最优雅方式是什么

在每次迭代中进行一次测试,结果如下所示:

// "first item done" flag
bool firstDone = false;

// items is an IEnumerable<something>
foreach (var item in items)
{
    if (!firstDone)
    {
        // do this only once
        ProcessDifferently(item);
        firstDone = true;
        continue;
    }

    ProcessNormally(item);
}
它将调用两次
GetEnumerator
,我希望避免这种情况(例如,对于Linq到Sql的情况)


如果需要对代码执行多次操作,您将如何执行此操作?

如果需要在多个位置执行此操作,我将提取一个方法:

public void Process<T>(IEnumerable<T> source,
                       Action<T> firstAction,
                       Action<T> remainderAction)
{
    // TODO: Argument validation
    using (var iterator = source.GetEnumerator())
    {
        if (iterator.MoveNext())
        {
            firstAction(iterator.Current);
        }
        while (iterator.MoveNext())
        {
            remainderAction(iterator.Current);
        }
    }
}

还有其他选择,但这取决于具体情况。

你可以用老式的方式:

var itemsList = items.ToList();
ProcessDifferently(itemsList[0]);

for(int i=1;i<itemsList.Count;i++)
{
   ProcessNormally(itemsList[i]);
}
var itemsList=items.ToList();
处理方式不同(itemsList[0]);
对于(inti=1;i,还有另一种方法:

    private static void Main(string[] args)
    {
        var testdata = new[] { "a", "b", "c", "d", "e" };

        var action = FirstThenRest<string>(
            s => Console.WriteLine("First: " + s),
            s => Console.WriteLine("Rest: " + s));

        foreach (var s in testdata)
            action(s);
    }

    public static Action<T> FirstThenRest<T>(Action<T> first, Action<T> rest)
    {
        Action<T> closure = t =>
                            {
                                first(t);
                                closure = rest;
                            };

        return t => closure(t);
    }
没有条件。:D


编辑:“头”和“尾”可能是更好的术语,但我现在懒得去更改它。

谢谢,干净整洁。完全符合我的要求。这将适用于列表和数组,但我需要对IEnumerable执行相同的操作,而不需要重复两次。啊,是的,你是对的。为了清晰起见,我修改了代码示例。使用skeets答案-非常好。
var itemsList = items.ToList();
ProcessDifferently(itemsList[0]);

for(int i=1;i<itemsList.Count;i++)
{
   ProcessNormally(itemsList[i]);
}
    private static void Main(string[] args)
    {
        var testdata = new[] { "a", "b", "c", "d", "e" };

        var action = FirstThenRest<string>(
            s => Console.WriteLine("First: " + s),
            s => Console.WriteLine("Rest: " + s));

        foreach (var s in testdata)
            action(s);
    }

    public static Action<T> FirstThenRest<T>(Action<T> first, Action<T> rest)
    {
        Action<T> closure = t =>
                            {
                                first(t);
                                closure = rest;
                            };

        return t => closure(t);
    }
First: a
Rest: b
Rest: c
Rest: d
Rest: e