|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Casting RulesPublic Interface IEntity End Interface Public Class TestEntity Implements IEntity End Class Public Interface IRepository(Of T As {IEntity}) End Interface Public Interface IConcreteRepository Inherits IRepository(Of TestEntity) End Interface Public Class ConcreteRepository Implements IConcreteRepository End Class Public Class Factory Public Shared Function Create(Of TRepository As {Class, IRepository(Of TEntity)}, TEntity As {IEntity})() Return New ConcreteRepository() End Function End Class I get casting exception on the line Dim Repository As IRepository(Of IEntity) = Factory.Create(Of IConcreteRepository, TestEntity)() What am I missing? The exception states Unable to cast object of type 'ConcreteRepository' to type 'IRepository`1[IEntity]'. Cheers, Aeden On 2007-11-02 15:57:23 -0700, Aeden Jameson <aeden.jame***@gmail.com> said:
> [...] I believe this is because generics don't support covariant generics. > I get casting exception on the line > > Dim Repository As IRepository(Of IEntity) = Factory.Create(Of > IConcreteRepository, TestEntity)() > > What am I missing? > > The exception states > > Unable to cast object of type 'ConcreteRepository' to type > 'IRepository`1[IEntity]'. Your ConcreteRepository class implements IConcreteRepository, which inherits IRepository<TestEntity>, and not IRepository<IEntity>. You would need the latter in order to successfully perform the cast. The reasoning behind this has to do with what a generic class _could_ do with the concrete type for the class. In particular, if you could cast down to a base class like that, then the possibility would arise that something in the generic class would replaces some instance of TestEntity with some instance of a different IEntity-derived class, which would cause a problem later in the code that had the TestEntity-specific concrete class. By requiring the generic type parameter to always be the actual type, this sort of problem is avoided. It does lead to less-flexible code such as in the example you're running into, but along with that comes compile-time type safety. If you don't want compile-time type safety, you should either not use generics, or make the IRepository<> generic use IEntity instead of TestEntity. Pete |
|||||||||||||||||||||||