Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics - Using parent class to specify type in generics

Tags:

c#

generics

I am looking at some covariance/contravariance stuff, I have a much wider question but it all boils down to this:

GenericRepository<BaseEntity> repo = new GenericRepository<ProductStyle>(context);

This doesn't work, even though BaseEntity is the parent abstract class of ProductStyle, is there a way of achieving this?

like image 235
Daniel Dawes Avatar asked Aug 13 '13 11:08

Daniel Dawes


People also ask

How do you declare a generic type in a class?

A Generic Version of the Box Class To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class.

How do you define generic type?

Definition: “A generic type is a generic class or interface that is parameterized over types.” Essentially, generic types allow you to write a general, generic class (or method) that works with different types, allowing for code re-use.

How do I restrict a generic type in Java?

Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.

Can generics take multiple type parameters?

Multiple parametersYou can also use more than one type parameter in generics in Java, you just need to pass specify another type parameter in the angle brackets separated by comma.


1 Answers

The only way of doing that is with an out generic restriction (which will make it hard to save objects, but fine to retrieve them), on an interface (not a class). If you have:

interface IGenericRepository<out T> {...}

then an IGenericRepository<ProductStyle> can be assigned to a variable of type IGenericRepository<BaseEntity>, since all ProductStyle are also BaseEntity, and we have restricted ourselves to covariant / out usage:

IGenericRepository<BaseEntity> tmp = GetRepo<ProductStyle>(context);
// note that the right-hand-side returns IGenericRepository<ProductStyle>
...
private IGenericRepository<T> GetRepo(...) {...}

Note, however, that this covariant / out usage makes it impossible to do things like:

interface IGenericRepository<out T>
{
    T Get(int id); // this is fine, but:
    void Save(T value); // does not compile; this is not covariantly valid
}
like image 126
Marc Gravell Avatar answered Oct 20 '22 09:10

Marc Gravell