How to create a generic extension method?

C#Generics

C# Problem Overview


I want to develop a Generic Extension Method which should arrange the string in alphabetical then by lengthwise ascending order.

I mean

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

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

What is the way to develop Generic Extension Method?

I tried :

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

I received :

>Error 1: T does not contain definition for Length > >Error 2: can not convert System.Linq.IOrderedEnumerable to T[].

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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

Solution 3 - C#

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.

Solution 4 - C#

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

Solution 5 - C#

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

Solution 6 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser215675View Question on Stackoverflow
Solution 1 - C#Darin DimitrovView Answer on Stackoverflow
Solution 2 - C#Maximilian MayerlView Answer on Stackoverflow
Solution 3 - C#Paul TurnerView Answer on Stackoverflow
Solution 4 - C#Alex BagnoliniView Answer on Stackoverflow
Solution 5 - C#Christian HayterView Answer on Stackoverflow
Solution 6 - C#David HedlundView Answer on Stackoverflow