tags:

views:

383

answers:

7

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

I am new to generics. What is the way to develop Generic Extension Method?

I tried :

public static class ExtensionOperation
    {
        public static T[] AplhaLengthWise<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[].

+6  A: 

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 ExtensionOperstion
{
    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 that:

string[] names = { "Jon", "Marc", "Joel", "Thomas", "Copsey", "Konrad", "Andrew", "Brian", "Bill" };
var result = names. AlphaLengthWise(a => a.Length);
Darin Dimitrov
Thanks you very much Drain.
I find myself using techniques like this `lengthProvider` a lot with generic code. It's just one more reason I love lambdas so much. :D
Greg D
+3  A: 

Having a generic method that only works on strings doesn't really make a whole lot of sense...

Jason Punyon
A: 

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.

David Hedlund
Changing T[] to IEnumerable<T> won't demand Length property for elements.
Arnis L.
it sure won't. that part of the answer was with regards to the second error. `IOrderedEnumerable<T>` implements `IEnumerable<T>`, so that would solve that part of the problem. As for the `Length` property, my suggestion was that `ToString()` was used to ensure a string, or, if he new he'd always be dealing with strings, to change `T` to `string`.
David Hedlund
+8  A: 

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;
    }
}
Maximilian Mayerl
Yes, you are right. Thanks for pointing that out, I'll edit my answer.
Maximilian Mayerl
Why `string[]` and not `IEnumerable<String>`? You could remove the `.ToArray()` and leave it deferred (if I am not mistaken).
Alex Bagnolini
Damned 30 seconds interval on posting comments :(
Alex Bagnolini
A: 

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);
    }
}
Alex Bagnolini
+1  A: 

Copy how Microsoft do 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);
    }
}
Christian Hayter
LOL - I corrected the non obvious spelling mistake and missed the obvious one. :-)
Christian Hayter
+1  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.

Programming Hero