如何创建泛型扩展方法?

我想开发一个通用扩展方法,它应该按字母顺序排列字符串,然后按纵向升序。

我是说

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.IOrderedEnumerable转换为 T[]

108451 次浏览

The first error is because Length is a property of the String class while in your generic version the type of the T parameter is not known. It could be any type.

The second error is because you return just the query object but not the actual result. You might need to call ToArray() before returning.

With little modifications you could come up with this:

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);
}
}

Which you could use like this:

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

You want to use IEnumerable<T> instead of T[]. Other than that, you won't be able to use Length of T, since not all types has a Length property. You could modify your extension method to .OrderBy(a => a.ToString().Length)

If you know you'll always be dealing with strings, use IEnumerable<String> rather than IEnumerable<T>, and you'll be able to access the Length property immediately.

Why do you want to do this generically? Just use

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

I want to develop a Generic Extension Method which should arrange the strings in alphabetical then ...

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

Copy how Microsoft does it:

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);
}
}

I think you may be a little confused to the purpose of generics.

Generics are a way to tailor a class or method to a specific type. A generic method or class is designed to work for any type. This is most easily illustrated in the List<T> class, where it can be tailored to be a list of any type. This gives you the type-safety of knowing the list only contains that specific type.

Your problem is designed to work on a specific type, the string type. Generics are not going to solve a problem which involves a specific type.

What you want is a simple (non-generic) Extension Method:

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);
}
}

Making the argument and the return type IEnumerable<string> makes this a non-generic extension method which can apply to any type implementing IEnumerable<string>. This will include string[], List<string>, ICollection<string>, IQueryable<string> and many more.