I have a couple of classes that implement an interface, IFoo. I need to display a list of objects of these classes in a table, which I'd like to be able to sort by any arbitrary column in the table. So, the data source for the table is a List<IFoo>
.
The problem I've run into is that the standard way of implementing IComparable
or IComparer
for objects that are used in a list requires a static method, but static methods aren't allowed in interfaces. So, the question boils down to this: how does one sort a List<IFoo>
?
IComparable
I don't know what gives you the idea that you need to be using a static method, but it's not correct.
You can force all your IFoo
implementers to implement IComparable<IFoo>
by adding it to IFoo
:
interface IFoo : IComparable<IFoo>
{
int Value { get; set; } // for example's sake
}
class SomeFoo : IFoo
{
public int Value { get; set; }
public int CompareTo(IFoo other)
{
// implement your custom comparison here...
return Value.CompareTo(other.Value); // e.g.
}
}
Then simply sort your List<IFoo>
like so:
list.Sort();
Sorting by an arbitrary column
You initially stated you want to sort by an arbitrary column in a table of IFoo objects. This is more complex; you need to be able to sort a list of objects by any one of their public properties, so the basic IComparable<IFoo>
implementation above isn't going to cut it.
The solution is to create a PropertyComparer<T>
class which implements IComparer<T>
, and will sort by any property of T
. You could write it specifically for IFoo
, but at some point every developer tends to come up against this problem and ends up writing a generic property compararer that will try to sort any type. As a result you can google "c# property comparer" and you're sure to get several hits. Here's a simple one:
http://www.codeproject.com/Articles/16200/Simple-PropertyComparer
I am not sure what problem you are running into because I just ran a quick test and could sort a list of IFoo. See below for how I did this. If this does not fit your need, could you maybe give more detail?
var fooList = new List<IFoo>{new testFoo{key=3}, new testFoo{key=1}};
fooList.Sort(
delegate(IFoo obj1, IFoo obj2){return obj1.key.CompareTo(obj2.key);});
Interface and Concrete
public interface IFoo
{
int key{get;set;}
}
public class testFoo:IFoo
{
public int key {get;set;}
}
If you are using C# 3/4, you can use a lambda expression..
This example shows how you can sort by different properties of the IFoo interface:
void Main()
{
List<IFoo> foos = new List<IFoo>
{
new Bar2{ Name = "Pqr", Price = 789.15m, SomeNumber = 3 },
new Bar2{ Name = "Jkl", Price = 444.25m, SomeNumber = 1 },
new Bar1{ Name = "Def", Price = 222.5m, SomeDate = DateTime.Now },
new Bar1{ Name = "Ghi", Price = 111.1m, SomeDate = DateTime.Now },
new Bar1{ Name = "Abc", Price = 123.45m, SomeDate = DateTime.Now },
new Bar2{ Name = "Mno", Price = 564.33m, SomeNumber = 2 }
};
foos.Sort((x,y) => x.Name.CompareTo(y.Name));
foreach(IFoo foo in foos)
{
Console.WriteLine(foo.Name);
}
foos.Sort((x,y) => x.Price.CompareTo(y.Price));
foreach(IFoo foo in foos)
{
Console.WriteLine(foo.Price);
}
}
interface IFoo
{
string Name { get; set; }
decimal Price { get; set; }
}
class Bar1 : IFoo
{
public string Name { get; set; }
public decimal Price { get; set; }
public DateTime SomeDate { get; set; }
}
class Bar2 : IFoo
{
public string Name { get; set; }
public decimal Price { get; set; }
public int SomeNumber { get; set; }
}
Output:
Abc
Def
Ghi
Jkl
Mno
Pqr
111.1
222.5
333.33
444.25
555.45
666.15