0

How do I re-write this sort code sample so it's using a generic extension instead of the second line?

I would like something like thi

var foosSorted = Unit.Foos().MyGenericSortFunction();

My working code

var foosSorted = Unit.Foos(); // Not sorted yet
foosSorted.Sort((x, y) => string.Compare(x.Name, y.Name));

How far I got with the generic extension

public static class ObjectExtension
{
    public static T Sort<T>(this T list) where T : ???
    {
        return list.Sort((x, y) => string.Compare(x.Name, y.Name));
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
radbyx
  • 9,352
  • 21
  • 84
  • 127
  • I can maybe solve it with this linq instead ` var foosSorted = Unit.GetFoos().OrderBy(f => f.Name).ToList(); ` but I would still really like to know how to make this with a generic extion solution, because I am so bad with the generic part. – radbyx Jun 29 '16 at 19:00
  • @Shiva yes I saw that question right after too. But I would still like to learn the generic alternative. – radbyx Jun 29 '16 at 19:03
  • 1
    You should go with this answer http://stackoverflow.com/a/26406452/1789202 – CSharpie Jun 29 '16 at 19:07
  • 1
    @Shiva how's this duplicate? OP knows how to sort a list. Needs a generic way which is not in scope of duplicate link. – Nikhil Vartak Jun 29 '16 at 19:21
  • 1
    `OrderBy` *is* the generic solution. Why write another one? – Panagiotis Kanavos Jun 30 '16 at 15:04

2 Answers2

1

Your parameter should be the collection of your type, so you'll be able to treat it as a collection, and access the Name property:

public static class ObjectExtension
{
    public static List<Foo> MyGenericSortFunction(this List<Foo> list)
    {
        list.Sort((x, y) => string.Compare(x.Name, y.Name));
        return list;
    }
}

You wouldn't use a generic here because you specifically need to use Name, which is a property of your Foo class. If it was defined in an interface, you could make your extension generic to the interface.

Note that this edits the existing list, rather than returning a new list like LINQ would do.

Joe Enos
  • 39,478
  • 11
  • 80
  • 136
  • Can you replace `Foo` with `T` ? Because sometimes my class i Unit and sometimes it's Group to be precise. – radbyx Jun 29 '16 at 19:02
  • You could also pass an expression which points to the property you wanted to compare, like `MySort(x => x.Propname)`, that way you could compare any type for sorting – Charleh Jun 29 '16 at 19:03
  • 1
    @radbyx Do your `Unit` and `Group` classes share an interface that exposes `Name`? If not they you cannot make this generic, you'd have to use `dynamic` instead. – juharr Jun 29 '16 at 19:03
  • No they don't share an Interface. All they have in common is that the have a Name property. Can you make the dynamic solution instead then? – radbyx Jun 29 '16 at 19:05
  • 1
    Is the name property the same type across the board? Make an interface to support it, and use that interface. – Chris Cudmore Jun 29 '16 at 19:08
  • Yes they are all `string`. You mean like creating and using your own `Comparator` ? – radbyx Jun 29 '16 at 19:11
1

Do you intend to make list elements generic? Like this:

public static class ObjectExtension
{
    public static List<T> Sort<T>(this List<T> list) where T : IFoo
    {
        list.Sort((x, y) => string.Compare(x.Name, y.Name));
        return list;
    }
}

public interface IFoo {
    string Name { get; }
}

public class Foo1 {
    public string Name { get; set; }
}

public class Foo2 {
    public string Name { get; set; }
}
Nikhil Vartak
  • 5,002
  • 3
  • 26
  • 32
  • Should Foo1 and Foo2 extend from IFoo? Because if not it looks like something I understand. – radbyx Jun 29 '16 at 19:13
  • 1
    I saw your comment *Because sometimes my class i Unit and sometimes it's Group*. So both of them should implement an interface, `IFoo`, for ex. – Nikhil Vartak Jun 29 '16 at 19:19