There is no type that you can specify that will get this to work. It is a
common misconception that inheritance and generic types are somehow related.
They aren't. Two concrete types built from the same generic type but with
different type parameters are no more related than a string and an integer.
Inheritance is based off the generic type itself. Therefore if you want to
be able to pass differing versions of a generic type to methods you must either
create a base class from which the generic type derives and which contains no generic
type parameters or an interface.
In .NET generic interfaces almost always derive from a non-generic interface with
equivalent functionality. Generic types generally implement generic interfaces,
and by definition, the non-generic base interface as well. Here is how you
can modify the above code to compile.
public abstract BaseDataObject
{
public abstract void PrintInformation ( );
public abstract object Data { get; }
}
public class DataObject<T> : BaseDataObject
{
}
public class PersonObject : DataObject<Person> { ... }
public class JobObject : DataObject<Job> { ... }
public class DebugInformation
{
public void PrintInformation ( BaseDataObject data )
{
data.PrintInformation();
}
}
Not quite as clean as we would like. An interface would do better here.
public interface IDataObject
{
void PrintInformation ( );
object Data { get; }
}
public interface IDataObject<T> : IDataObject
{
T Data { get; }
}
public class DataObject<T> : IDataObject<T>
{
abstract T Data { get; }
object IDataObject.Data
{ get { return this.Data; } }
}
public class PersonObject : DataObject<Person> { ... }
public class JobObject : DataObject<Job> { ... }
public class DebugInformation
{
public void PrintInformation ( IDataObject data )
{
data.PrintInformation();
}
}
Finally, as an alternative we could make the original PrintInformation
method generic and then use the generic interface we originally wrote.
public class DataObject<T>
{
public abstract void PrintInformation ( );
}
public class PersonObject : DataObject<Person> { ... }
public class JobObject : DataObject<Job> { ... }
public class DebugInformation
{
public void PrintInformation<T> (DataObject<T> data )
{
data.PrintInformation();
}
}
(Updated 24 Mar 2007 w/ alternative received from James Curran)