I have an object which could be compared to a DataTable/List which I am
trying to genericify.
I've spent about a day so far in refactoring and in the process gone
through some hoops and hit some dead ends.
I'm posting this to get some feedback on wether I'm going in the right
direction, and at the same time hopefully save others from going
through the process.
The starting point. I have a "Store" class which provides ways to get
hold of "Record"s...
public class Record {
}
public class Store
{
Record FindRecordById(int id)
{
// return a Record
}
public string StoreName { get {return "Store"}};
}
So my first attempt to use generics was this...
public class Record
{
}
public class Store<Rwhere R : Record
{
R FindRecordById(int id)
{
// return an R
}
public string StoreName { get {return "Store"}};
}
I wanted to pass Store<Record>s around and use them as a base class for
activities however I found that is not possible due to casting issues.
e.g. I can't cast Store<MyRecordto Store<Record>.
The best explanation is that you can't cast a List<MyClassto a
List<objectas is it will allow the caster to add objects to a MyClass
based lists!
So I tried adding an interface into the structure:
public interface IStore
{
string StoreName {get;}
}
public class Store<R: IStore where R : Record
{
public string StoreName { get {return "Store"}};
}
I can now pass the IStore around without the casting problem.
Then I came to the issue that I wanted to add methods to the interface
based on the generic R class.
I can't make it a generic interface as this will bring me back to the
original problem.
So I came up with this structure:
public interface IStore
{
Record FindRecordById(int id);
}
public class Store<R: IStore where R : Record
{
Record IStore.FindRecordById(int id)
{
// return a Record
}
public R FindRecordById(int id)
{
return (R)((IStore)this).FindRecordById(id);
}
}
Thus, if its cast as an IStore I have access to the non generic method,
and if its cast to the generic class I get the generic one.
They don't interfere with each other as they are visible at different
times.
Just to complete the story, I also wanted to be able to have non
generic class wrappers to my store classes but still be able to
subclass in a generic way. So I came up with this:
public class MyRecord : Record
{
}
public class MyStore<R: Store<Rwhere R : MyRecord, new()
{
}
public class MyStore : MyStore<MyRecord// non generic version
{
}
// a subclass of MyStore...
public class MyOtherRecord : MyRecord
{
}
public class MyOtherStore<R: MyStore<Rwhere R : MyOtherRecord,
new()
{
}
public class MyOtherStore : MyOtherStore<MyOtherRecord>
{
}
I've just thought. With this structure I will not be able to cast a
MyOtherStore to a MyStore. This could be an issue. I'll sleep on that
one.
All this seems to be working (compiling anyhow). I still have a lot of
code to refactor.
I'm also thinking, the whole point of the exercise was to reduce
potential errors with tighter compile time type checking, but it seems
I'm ending up doing more run-time casting thus defeating the point! I
think it would still help in reducing errors in business logic which
uses these classes, which might mean its worth while.
Any comments would be appreciated.
Tigger