簡體   English   中英

帶有自定義比較器的 OrderBy 的 Linq 語法<T>

[英]Linq syntax for OrderBy with custom Comparer<T>

對於具有自定義排序比較器的任何給定 Linq 表達式,有兩種格式:

格式 1

var query =
    source
    .Select(x => new { x.someProperty, x.otherProperty } )
    .OrderBy(x => x, new myComparer());

格式 2

var query =
    from x in source
    orderby x // comparer expression goes here?
    select new { x.someProperty, x.otherProperty };

題:
第二種格式的 order-by 表達式的語法是什么?

不是問題:
如何使用第一種格式中所示的自定義比較器。

紅利:
上面列出的兩種 Linq 格式是否有實際的正式名稱?

第二種格式的 order-by 表達式的語法是什么?

它不存在。 orderby 條款文檔

您還可以指定自定義比較器。 但是,它只能通過使用基於方法的語法來使用。


如何使用第一種格式的自定義比較器。

你寫得對。 您可以在編寫時傳遞IComparer<T>


上面列出的兩種 Linq 格式是否有實際的正式名稱?

格式 1 稱為“基於方法的語法”(來自上一個鏈接),格式 2 稱為“查詢表達式語法”(來自此處)。

如何使用第一種格式中所示的自定義比較器。

您不能使用該格式的自定義比較器。

上面列出的兩種 Linq 格式是否有實際的正式名稱?

格式 1 是方法語法,格式 2 是“查詢語法”,

題:

這在查詢語法中是不可能的,因為沒有重載。

不是問題:

僅當您使用反射來比較對象時,才可以使用匿名類型的比較器,最好使用類型化實現進行比較。

如果你不想創建一個類型化的實現,你可以使用一個Tuple

var query =
    source
    .Select(x => new Tuple<string, int>(x.someProperty, x.otherProperty))
    .OrderBy(x => x, new MyComparer());

public class MyComparer : IComparer<Tuple<string, int>>
{
  public int Compare(Tuple<string, int> x, Tuple<string, int> y)
  {
    return x.Item1.CompareTo(y.Item1);
  }
}

紅利:

  • 查詢語法或理解語法
  • 方法語法或擴展方法語法

這不一定回答最初的問題,但它在某種程度上擴展了概述的一些可能性。 我張貼這個以防其他人遇到類似的問題。 此處發布的解決方案概述了在其他情況下可能有用的選項的通用順序。 在這個例子中,我想按不同的屬性對文件列表進行排序。

/// <summary>
/// Used to create custom comparers on the fly
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericCompare<T> : IComparer<T>
{
    // Function use to perform the compare
    private Func<T, T, int> ComparerFunction { set; get; }

    // Constructor
    public GenericCompare(Func<T, T, int> comparerFunction)
    {
        ComparerFunction = comparerFunction;
    }

    // Execute the compare
    public int Compare(T x, T y)
    {

        if (x == null || y == null) 
        {
            // These 3 are bell and whistles to handle cases where one of the two is null, to sort to top or bottom respectivly
            if (y == null && x == null) { return 0; }
            if (y == null) { return 1; }
            if (x == null) { return -1; }
        }

        try
        {
            // Do the actual compare
            return ComparerFunction(x, y);
        }
        catch (Exception ex)
        {
            // But muffle any errors
            System.Diagnostics.Debug.WriteLine(ex);
        }

        // Oh crud, we shouldn't be here, but just in case we got an exception.
        return 0;
    }
}

然后在實施中……

        GenericCompare<FileInfo> DefaultComparer;

        if (SortOrder == SORT_FOLDER_FILE)
        {
            DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
            {
                return fr1.FullName.ToLower().CompareTo(fr2.FullName.ToLower());
            });
        }
        else if (SortOrder == SORT_SIZE_ASC)
        {
            DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
            {
                return fr1.Length.CompareTo(fr2.Length);
            });
        }
        else if (SortOrder == SORT_SIZE_DESC)
        {
            DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
            {
                return fr2.Length.CompareTo(fr1.Length);
            });
        }
        else
        {
            DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
            {
                return fr1.Name.ToLower().CompareTo(fr2.Name.ToLower());
            });
        }

        var ordered_results = (new DirectoryInfo(@"C:\Temp"))
                .GetFiles()
                .OrderBy(fi => fi, DefaultComparer);

最大的優點是你不需要為每個訂單創建一個新的類,你只需連接一個新的 lambda。 顯然,這可以以各種方式擴展,因此希望它可以幫助某人,某地,某時。

暫無
暫無

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

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