How to create an abstract base class IComparable that does not compare two separate inherited classes?

(C #, VS2008). In the program I'm working on, I have many objects that have an identifier and an IComparable implementation, so List <> - s of different objects can be easily found by identifier. Since I hate copy / paste code, I thought I would drop this functionality to the base class, for example:

using System; namespace MyProg.Logic { abstract class IDObject : IComparable<IDObject> { private int miID; public int ID { get { return miID; } set { miID = value; } } public IDObject(int ID) { miID = ID; } #region IComparable<IDObject> Members int IComparable<IDObject>.CompareTo(IDObject other) { return miID.CompareTo(other.miID); } #endregion } } 

The drawback that I see in this is that two separate classes, each of which inherits it, will be directly comparable using .CompareTo (), and I was hoping to ensure that every class that inherits IDObject compares only with the others from the same class, so I was hoping to figure out how to do this, and came up with this

 using System; namespace MyProg.Logic { abstract class IDObject : IComparable<T> where T : IDObject { private int miID; public int ID { get { return miID; } set { miID = value; } } public IDObject(int ID) { miID = ID; } #region IComparable<T> Members int IComparable<T>.CompareTo(T other) { return miID.CompareTo(other.miID); } #endregion } } 

But this gives a compilation error "Restrictions are not allowed for non-generic declarations"

Looking at this, I am sure there is a way to do something like this so that each class is comparable to other instances of the same class, but I cannot separate the syntax.

+7
generics inheritance c #
source share
2 answers

You can use the Curiously Recurring Template Pattern to solve this problem.

 abstract class Base<T> : IComparable<T> where T : Base<T> { public int Rank { get; set; } // Order instances of derived type T by Rank public int CompareTo(T other) { return Rank.CompareTo(other.Rank); } } class Foo : Base<Foo> {} class Bar : Base<Bar> {} static class Program { static void Main() { var foo1 = new Foo { Rank = 1 }; var foo2 = new Foo { Rank = 2 }; var bar1 = new Bar { Rank = 1 }; var bar2 = new Bar { Rank = 2 }; Console.WriteLine(foo1.CompareTo(foo2)); Console.WriteLine(bar2.CompareTo(bar1)); //error CS1503: Argument '1': cannot convert from 'Bar' to 'Foo' //Console.WriteLine(foo1.CompareTo(bar1)); } } 
+12
source share

I think you have more problems than just checking that the types of the derived classes are the same. You also make the derived class responsible for creating a unique identifier. This requires the derived class to know what other identifiers were previously assigned. Actually, this requires a factory class. You need to ensure this by creating a protective constructor for your abstract class.

Not very practical. If the identifier is just an opaque number that sets the identifier of the object, then consider assigning the identifier yourself. Use a static member to track the last assigned. Now it is becoming simple, and you no longer need to worry about the types of derived classes.

+2
source share

All Articles