2009-12-01 72 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>等等。