簡體   English   中英

linq concat如何在后台運行?

[英]How does linq concat work under the hood?

我正在考慮替換如下代碼:

        foreach (var meshCut in meshCuts0)
        {
            ComputePolygons(meshCut, polygons);
        }
        foreach (var meshCut in meshCuts1)
        {
            ComputePolygons(meshCut, polygons);
        }

與linq看起來像這樣:

        meshCuts0.Concat(meshCuts1).ForEach(m => ComputePolygons(m, polygons));

我不知道linq是如何實現的,因此我不確定性能的后果。 我希望得到一些幫助。

1)

Concat將創建一個列表副本,還是只是一個枚舉器,執行以下操作:

    public static IEnumerable<T> Concat<T>(IEnumerable<T> a, IEnumerable<T> b)
    {
        foreach (var t in a)
        {
            yield return t;
        }
        foreach (var t in b)
        {
            yield return t;
        }
    }

2)

在Mono上會不會有相同的行為?

3)

是否有任何參考說明如何為注重性能的人實現linq api函數?

謝謝!

編輯

好的,沒有ForEach,所以假設我還定義了以下內容:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach(T item in source)
        action(item);
}

真正的問題是,僅因為精簡代碼,Concat是否會成為代價高昂的開銷,這要歸功於注釋,我現在知道不是。

編輯2

啊,喬恩·斯凱特(Jon Skeet)建議不要添加ForEach ...所以我不會!

http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

首先,僅當您還在 IEnumerable<T>上引入ForEach擴展方法時,您的代碼才能工作。 我建議您不要這樣做-出於我同意的原因,請參閱Eric Lippert的博客文章

我建議您將其寫為:

foreach (var meshCut in meshCuts0.Concat(meshCuts1))
{
    ComputePolygons(meshCut, polygons);
}

Concat表現很好-只需在第一個序列上進行迭代,然后在第二個序列上進行迭代,就可以生成項目。 不會緩沖所有元素。 對於所添加的額外間接級別,性能會受到很小的影響,僅此而已。

我希望Mono的行為方式相同Concat 非常簡單。 實際上,由於Mono是開源的,因此您可以自己檢查它 (當然,它可能會隨着時間推移而移動...)

不久前,我在博客中詳細介紹了LINQ to Objects,從頭開始重新實現了整個過程,並記錄了其性能的各個方面,包括需要改進的地方。 有關更多詳細信息,請參閱我的Edulinq博客系列

這就是linq concat在后台運行的方式。

Microsoft .net Framework 4.0:

public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
    if (first == null) throw Error.ArgumentNull("first");
    if (second == null) throw Error.ArgumentNull("second");
    return ConcatIterator<TSource>(first, second); 
}

static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second) { 
    foreach (TSource element in first) yield return element;
    foreach (TSource element in second) yield return element; 
}

Mono(來源: https : //github.com/mono/mono/blob/master/mcs/class/System.Core/System.Linq/Enumerable.cs#L584

public static IEnumerable<TSource> Concat<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
{
    Check.FirstAndSecond (first, second);

    return CreateConcatIterator (first, second);
}

static IEnumerable<TSource> CreateConcatIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second)
{
    foreach (TSource element in first)
        yield return element;
    foreach (TSource element in second)
        yield return element;
}

具體答案:

  1. 它沒有創建任何副本,而只是枚舉。

  2. 是。

  3. 對於注重性能的人來說,源代碼是最好的。

  1. 它的工作就像您描述的一樣。 您可以下載名為JetBrains dotPeek-.net decompiler的免費工具。 您可以加載每個程序集,甚至可以將標准程序集進行反編譯並獲取源代碼。 如果查看程序集System.Core,名稱空間System.Linq,類Enumerable,則可以看到以下內容:

     public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) { if (first == null) throw Error.ArgumentNull("first"); if (second == null) throw Error.ArgumentNull("second"); return ConcatIterator<TSource>(first, second); } static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second) { foreach (TSource element in first) yield return element; foreach (TSource element in second) yield return element; } 

    談論LINQ-這很懶,每種linq擴展方法都使用延遲的計算。 有個好人Jon Skeet,他有一個博客。 有許多名為“將LINQ重新實現為對象:零件”的文章,所有這些文章都可以通過標簽“ linq”找到: 鏈接

  2. Mono是開源項目。 您可以在github上找到源。 可在此處建立Enumerable類: link 以及Concat的源代碼:

     public static IEnumerable<TSource> Concat<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second) { Check.FirstAndSecond (first, second); return CreateConcatIterator (first, second); } static IEnumerable<TSource> CreateConcatIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second) { foreach (TSource element in first) yield return element; foreach (TSource element in second) yield return element; } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM