IComparer Question

I

INeedADip

I am trying to use a generic (reflection) IComparer class to sort a
generic list but I get the error:
Unable to cast object of type 'GenericComparer' to type
'System.Collections.Generic.Icomparer `1[AccountDB.Queue]'

My code looks like the following:

List<AccountDB.Queue> oList = getAllQueuesFunction();
List.Sort(New GenericComparer("QueueName")); <-- Error

My class looks like:

public class GenericComparer : IComparer
{
string propertyName;

public GenericComparer(string propertyName)
{
this.propertyName = propertyName;
}

public int Compare(object x, object y)
{
// gets the value of the x property
PropertyInfo property =
x.GetType().GetProperty(propertyName);
object valueOfX = property.GetValue(x, null);

// gets the value of the y property
property = y.GetType().GetProperty(propertyName);
object valueOfY = property.GetValue(y, null);

// now makes the comparsion
return ((IComparable)valueOfX).CompareTo(valueOfY);
}
}

Hopefully you can see what I am trying to accomplish. Am I approaching
this the wrong way? Any suggestions or Comments?
 
J

Jon Skeet [C# MVP]

INeedADip said:
I am trying to use a generic (reflection) IComparer class to sort a
generic list but I get the error:
Unable to cast object of type 'GenericComparer' to type
'System.Collections.Generic.Icomparer `1[AccountDB.Queue]'

My code looks like the following:

List<AccountDB.Queue> oList = getAllQueuesFunction();
List.Sort(New GenericComparer("QueueName")); <-- Error

You've implemented System.Collections.IComparer. You need to implement
System.Collections.Generic.IComparer<T>.
 
S

Stoitcho Goutsev \(100\)

Hi,

You get this error because your GenericComparer implements IComparer not
IComparer<T>. Despite the same name both interfaces are different.

If you look at the Sort method of List<T> generic you'll see that it is
declared as

public void Sort (
IComparer<T> comparer
)You need to declare you comparer aspublic class GenericComparer :
IComparer<[the type of the elements in the list]>or you can create generic
comparer and specify the type of the elements upon creation.-- HTHStoitcho
 
I

INeedADip

Any ideas on how I should approach this?

I thought maybe IComparer<object> but I can't quite get it to work..
 
J

Jon Skeet [C# MVP]

INeedADip said:
Any ideas on how I should approach this?

I thought maybe IComparer<object> but I can't quite get it to work..

Make your comparer generic as well. Something like (untested):

public class GenericComparer<T> : IComparer<T>
{
string propertyName;

public GenericComparer(string propertyName)
{
this.propertyName = propertyName;
}

public int Compare(T x, T y)
{
// gets the value of the x property
PropertyInfo property = x.GetType()
.GetProperty(propertyName);
object valueOfX = property.GetValue(x, null);

// gets the value of the y property
property = y.GetType().GetProperty(propertyName);
object valueOfY = property.GetValue(y, null);

// now makes the comparsion
return ((IComparable)valueOfX).CompareTo(valueOfY);
}
}

Note that I'm still using GetType() in the above rather than typeof(T)
in case the properties aren't provided by T itself, but by a class
derived from T.
 
I

INeedADip

Thank you very much for the help.
I'm sure there are better ways of doing this, but this seems like a
pretty good way to sort my objects (without making a bunch of
IComparer<T> classes).
I wanted to post the final solution here incase anyone else is looking
for something similar, it sure would have saved me a lot of time.

This will allow you to sort on a List<T> of custom classes with simple
value type properties:

public enum GenericComparerSortDirection { Asc, Desc }

public class GenericComparer<T> : IComparer<T>
{

private string propertyName;
private GenericComparerSortDirection theDirection;

public GenericComparer(string propertyName,
GenericComparerSortDirection eSortDirection)
{
this.propertyName = propertyName;
this.theDirection = eSortDirection;
}

public int Compare(T x, T y)
{
// gets the value of the x property
PropertyInfo property =
x.GetType().GetProperty(propertyName);
object valueOfX = property.GetValue(x, null);

// gets the value of the y property
property = y.GetType().GetProperty(propertyName);
object valueOfY = property.GetValue(y, null);

// now make the comparsion
if (this.theDirection == GenericComparerSortDirection.Asc)
return ((IComparable)valueOfX).CompareTo(valueOfY);
else
return ((IComparable)valueOfY).CompareTo(valueOfX);
}
}

Usage:

List<MyClass> lstSorted = getABunchOfObjects();
lstSorted.Sort(new GenericComparer<MyClass>("PropertyName",
GenericComparerSortDirection.Asc));
 
I

INeedADip

Thank you very much for the help.
I'm sure there are better ways of doing this, but this seems like a
pretty good way to sort my objects (without making a bunch of
IComparer<T> classes).
I wanted to post the final solution here incase anyone else is looking
for something similar, it sure would have saved me a lot of time.

This will allow you to sort on a List<T> of custom classes with simple
value type properties:

public enum GenericComparerSortDirection { Asc, Desc }

public class GenericComparer<T> : IComparer<T>
{

private string propertyName;
private GenericComparerSortDirection theDirection;

public GenericComparer(string propertyName,
GenericComparerSortDirection eSortDirection)
{
this.propertyName = propertyName;
this.theDirection = eSortDirection;
}

public int Compare(T x, T y)
{
// gets the value of the x property
PropertyInfo property =
x.GetType().GetProperty(propertyName);
object valueOfX = property.GetValue(x, null);

// gets the value of the y property
property = y.GetType().GetProperty(propertyName);
object valueOfY = property.GetValue(y, null);

// now make the comparsion
if (this.theDirection == GenericComparerSortDirection.Asc)
return ((IComparable)valueOfX).CompareTo(valueOfY);
else
return ((IComparable)valueOfY).CompareTo(valueOfX);
}
}

Usage:

List<MyClass> lstSorted = getABunchOfObjects();
lstSorted.Sort(new GenericComparer<MyClass>("PropertyName",
GenericComparerSortDirection.Asc));
 
N

Nicholas Paldino [.NET/C# MVP]

Instead of creating an implementation of IComparer<T>, you can just use
anonymous delegates as well (unless you need to use this implementation in a
good number of places).

Hope this helps.
 
I

INeedADip

Jon Skeet - Thank you very much for the help.
I'm sure there are better ways of doing this, but this seems like a pretty
good way to sort my objects (without making a bunch of IComparer<T>
classes).
I wanted to post the final solution here incase anyone else is looking for
something similar, it sure would have saved me a lot of time.

This will allow you to sort on a List<T> of custom classes with simple value
type properties:

public enum GenericComparerSortDirection { Asc, Desc }

public class GenericComparer<T> : IComparer<T>
{

private string propertyName;
private GenericComparerSortDirection theDirection;

public GenericComparer(string propertyName,
GenericComparerSortDirection eSortDirection)
{
this.propertyName = propertyName;
this.theDirection = eSortDirection;
}

public int Compare(T x, T y)
{
// gets the value of the x property
PropertyInfo property = x.GetType().GetProperty(propertyName);
object valueOfX = property.GetValue(x, null);

// gets the value of the y property
property = y.GetType().GetProperty(propertyName);
object valueOfY = property.GetValue(y, null);

// now make the comparsion
if (this.theDirection == GenericComparerSortDirection.Asc)
return ((IComparable)valueOfX).CompareTo(valueOfY);
else
return ((IComparable)valueOfY).CompareTo(valueOfX);
}
}

Usage:

List<MyClass> lstSorted = getABunchOfObjects();
lstSorted.Sort(new GenericComparer<MyClass>("PropertyName",
GenericComparerSortDirection.Asc));
 
I

INeedADip

I did think about that, but I use it so often, this was a better way...

Jon Skeet - Thank you very much for the help.
I'm sure there are better ways of doing this, but this seems like a
pretty good way to sort my objects (without making a bunch of
IComparer<T> classes).
I wanted to post the final solution here incase anyone else is looking
for something similar, it sure would have saved me a lot of time.

This will allow you to sort on a List<T> of custom classes with simple
value type properties:

public enum GenericComparerSortDirection { Asc, Desc }

public class GenericComparer<T> : IComparer<T>
{

private string propertyName;
private GenericComparerSortDirection theDirection;

public GenericComparer(string propertyName,
GenericComparerSortDirection eSortDirection)
{
this.propertyName = propertyName;
this.theDirection = eSortDirection;
}

public int Compare(T x, T y)
{
// gets the value of the x property
PropertyInfo property =
x.GetType().GetProperty(propertyName);
object valueOfX = property.GetValue(x, null);

// gets the value of the y property
property = y.GetType().GetProperty(propertyName);
object valueOfY = property.GetValue(y, null);

// now make the comparsion
if (this.theDirection == GenericComparerSortDirection.Asc)
return ((IComparable)valueOfX).CompareTo(valueOfY);
else
return ((IComparable)valueOfY).CompareTo(valueOfX);
}
}

Usage:

List<MyClass> lstSorted = getABunchOfObjects();
lstSorted.Sort(new GenericComparer<MyClass>("PropertyName",
GenericComparerSortDirection.Asc));
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top