2009-12-01 70 views
55

我想開發一個通用擴展方法,它應該按字母順序排列字符串,然後按照縱向升序排列。如何創建一個通用的擴展方法?

我的意思是

string[] names = { "Jon", "Marc", "Joel", 
        "Thomas", "Copsey","Konrad","Andrew","Brian","Bill"}; 

var query = names.OrderBy(a => a.Length).ThenBy(a => a); 

什麼是發展通用擴展方法的方法是什麼?

我嘗試:

public static class ExtensionOperation 
    { 
     public static T[] AlphaLengthWise<T>(this T[] names) 
     { 
      var query = names.OrderBy(a => a.Length).ThenBy(a => a); 
      return query; 
     } 
    } 

我接收:

錯誤1:T不包含定義長度

錯誤2:不能轉換到System.Linq.IOrderedEnumerableT[]

+4

爲什麼它應該是通用的,如果你只想安排字符串? – bniwredyc 2009-12-01 12:45:23

+6

@bniwredyc因爲'generic'聽起來很酷! :) – 2009-12-01 12:49:34

+0

非常感謝所有 – user215675 2009-12-01 12:56:00

回答

80

第一個錯誤是因爲LengthString類的屬性,而在你的通用版T參數的類型未知。它可以是任何類型。

第二個錯誤是因爲您只返回查詢對象而不是實際結果。您可能需要在返回前致電ToArray()

很少的修改,你能想出這樣的:

public static class ExtensionOperation 
{ 
    public static IEnumerable<T> AlphaLengthWise<T, L>(
     this IEnumerable<T> names, Func<T, L> lengthProvider) 
    { 
     return names 
      .OrderBy(a => lengthProvider(a)) 
      .ThenBy(a => a); 
    } 
} 

,你可以使用這樣的:

string[] names = { "Jon", "Marc", "Joel", "Thomas", "Copsey", "Konrad", "Andrew", "Brian", "Bill" }; 
var result = names. AlphaLengthWise(a => a.Length); 
+0

我發現我自己使用像'lengthProvider'這樣的技術有很多通用代碼。這只是我非常喜歡lambda的另一個原因。 :D – 2009-12-01 13:10:01

-1

你想用IEnumerable<T>而不是T[]。除此之外,您將無法使用LengthT,因爲並非所有類型都有Length屬性。您可以修改您的擴展方法.OrderBy(a => a.ToString().Length)

如果你知道你永遠可以處理字符串,使用IEnumerable<String>而不是IEnumerable<T>,你就可以立即訪問Length屬性。

+0

將T []更改爲IEnumerable 將不需要元素的長度屬性。 – 2009-12-01 12:46:21

+0

它肯定不會。答案的那部分是關於第二個錯誤。 'IOrderedEnumerable '實現'IEnumerable ',這樣就可以解決這個問題的一部分。至於'Length'屬性,我的建議是'ToString()'用於確保一個字符串,或者如果他是新的,他總是處理字符串,將'T'改爲'string'。 – 2009-12-01 13:12:59

14

爲什麼你想這樣做一般?只需使用

public static class ExtensionOperations 
{ 
    public static IEnumerable<string> AlphaLengthWise(this string[] names) 
    { 
     var query = names.OrderBy(a => a.Length).ThenBy(a => a); 
     return query; 
    } 
} 
+1

爲什麼'string []'而不是'IEnumerable '?你可以移除'.ToArray()'並且延遲它(如果我沒有弄錯的話)。 – 2009-12-01 12:51:15

2

我想開發一個通用的擴展方法應該安排在字母然後字符串 ...

public static class ExtensionOperation 
{ 
    public static IEnumerable<String> AplhaLengthWise(
            this IEnumerable<String> names) 
    { 
     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
} 
3

爲什麼你希望它是通用的?

只有當T具有Length屬性時,纔會生效,並且您將需要一個接口來執行該操作。

此外T必須是IComparable。

1

複製微軟是如何做的:

public static class ExtensionOperation { 
    // Handles anything queryable. 
    public static IOrderedQueryable<string> AlphaLengthWise(this IQueryable<string> names) { 
     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
    // Fallback method for non-queryable collections. 
    public static IOrderedEnumerable<string> AlphaLengthWise(this IEnumerable<string> names) { 
     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
} 
5

我想你可能有點糊塗仿製藥的目的。

泛型是一種將類或方法定製爲特定類型的方法。通用方法或類被設計用於類型的任何類型。這在List<T>類中最容易說明,它可以被定製爲任何類型的列表。這使您知道該列表僅包含該特定類型的類型安全性。

您的問題旨在處理特定類型的string類型。泛型不會解決涉及特定類型的問題。

你想要的是一個簡單的(非通用)擴展方法:

public static class ExtensionOperations 
{ 
    public static IEnumerable<string> AlphaLengthWise(
     this IEnumerable<string> names) 
    { 
     if(names == null) 
      throw new ArgumentNullException("names"); 

     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
} 

使該參數和返回值類型IEnumerable<string>使得這可以適用於任何類型的實施IEnumerable<string>非泛型擴展方法。這將包括string[],List<string>,ICollection<string>,IQueryable<string>等等。