簡體   English   中英

Linq中的這兩個語句之間有區別嗎?

[英]Is there a difference between these two statements in Linq?

這兩個語句之間是否有區別。 我做了一個測試,但在延遲執行的測試中,它失敗了。 有什么區別?

items.Where(w => w.Length >= length).Select(w => w.Substring(0, length)).Distinct();

(from a in items
                where a.Length >= 3
                select a.Substring(0, length)).Distinct();

他們對我讀得一樣,我相信也完全一樣嗎?

我假設3 vs length是錯別字。

過去之后,這里的竅門是: 試試吧 這里有一個很好的工具Sharplab.io- 這是兩個示例 ,在編譯和反編譯后,我們可以看到MN大致相同:

public void M()
{
    IEnumerable<string> enumerable = Enumerable.Distinct(Enumerable.Select(Enumerable.Where(items, new Func<string, bool>(<M>b__2_0)), new Func<string, string>(<M>b__2_1)));
}

public void N()
{
    IEnumerable<string> enumerable = Enumerable.Distinct(Enumerable.Select(Enumerable.Where(items, new Func<string, bool>(<N>b__3_0)), new Func<string, string>(<N>b__3_1)));
}

它們使用不同的編譯器生成的方法,但實現方式相同:

[CompilerGenerated]
private bool <M>b__2_0(string w)
{
    return w.Length >= length;
}

[CompilerGenerated]
private string <M>b__2_1(string w)
{
    return w.Substring(0, length);
}

[CompilerGenerated]
private bool <N>b__3_0(string a)
{
    return a.Length >= length;
}

[CompilerGenerated]
private string <N>b__3_1(string a)
{
    return a.Substring(0, length);
}

所以:我們可以得出結論,它們是相同的。

假設您打算where a.Length >= length寫,那么就沒有。 編譯器始終使用擴展方法將查詢語法轉換為等效語法。

您可以通過SharpLab看到它們-它們都可以編譯為以下形式:

[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
    public int length;

    internal bool <Query>b__0(string a)
    {
        return a.Length >= length;
    }

    internal string <Query>b__1(string a)
    {
        return a.Substring(0, length);
    }
}

public void Query(IEnumerable<string> items, int length)
{
    <>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
    <>c__DisplayClass0_.length = length;
    Enumerable.Distinct(Enumerable.Select(Enumerable.Where(items, new Func<string, bool>(<>c__DisplayClass0_.<Query>b__0)), new Func<string, string>(<>c__DisplayClass0_.<Query>b__1)));
}

您可以在查詢語法和擴展方法之間使用這種等效性。 編譯器使您可以對具有擴展名並定義了正確名稱的類型使用查詢語法,而不管它們是在IEnumerable<T>IQueryable<T>還是其他類型上定義的。

這是編譯器中“鴨式輸入”的一個示例,其中編譯器不關心特定類型的接口,而只是完全存在具有正確名稱和簽名的特定方法。

例如,這將編譯:

public class C {
    public void Query(IThing<string> thing) {
        var y = from x in thing
            select x;
    }
}

public interface IThing<T>
{
    T Foo { get; }   
}

public static class ThingExtensions
{
    public static IThing<T> Select<T>(this IThing<T> thing, Func<IThing<T>, IThing<T>> selector)
    {
        return selector(thing);
    }
}

例如,在Sprache解析器組合器庫中使用了該庫,該庫使您可以編寫如下解析器:

Parser<string> identifier =
    from leading in Parse.WhiteSpace.Many()
    from first in Parse.Letter.Once()
    from rest in Parse.LetterOrDigit.Many()
    from trailing in Parse.WhiteSpace.Many()
    select new string(first.Concat(rest).ToArray());

這里沒有IEnumerable<T>IQueryable<T> -庫僅使用正確的簽名定義擴展方法SelectSelectMany ,並且解析器愉快地編譯以上查詢語法以使用這些擴展方法。

暫無
暫無

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

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