Casting Rules

A

Aeden Jameson

Suppose I have the follwing


Public 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
 
P

Peter Duniho

[...]
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]'.

I believe this is because generics don't support covariant generics.
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
 

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