Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics and casting

Tags:

c#

generics

class B : A {}
class Sub<T> where T:A
{
//...
}

I want to store Sub instances in a collection.

var c = new List<Sub<A>>();
c.Add(new Sub<B>()); //doesn't work

However, to get it to actually work, I have to declare an interface and store instances of that interface.

interface IBase
{
    void DoStuff(A a);
}

var c = new List<IBase>();
c.Add(new Sub<B>()); //works

Is there a more elegant way of doing this?

like image 906
jameszhao00 Avatar asked Jun 08 '11 17:06

jameszhao00


People also ask

Does generics eliminate the use of casting?

As mentioned previously, generics can eliminate the requirement for casting.

What is generic type casting?

Java generics is just a language feature to help us catch the type-casting errors at compile time itself. The compiler removes all the generic and parameterized types by a technique called type erasure. For example, Our generic Node class, public class Node<N> { will appear as public class Node { in the bytecode.

Do generics prevent type cast errors?

Implementing generics into your code can greatly improve its overall quality by preventing unprecedented runtime errors involving data types and typecasting.

What is casting in Java?

Type casting is when you assign a value of one primitive data type to another type. In Java, there are two types of casting: Widening Casting (automatically) - converting a smaller type to a larger type size. byte -> short -> char -> int -> long -> float -> double.


2 Answers

No. Instantiations of a generic type with different type arguments are completely unrelated. The only way you can get them in the same list is by having the list use a common non-generic base class or interface, as you did here.

You can achieve an approximation of what you want by using a covariant generic interface:

class A { }
class B : A { }

interface ISub<out T> where T : A
{
    // Members go here
}

class Sub<T> : ISub<T> where T : A
{
    // Members go here.
}

Which can be used as follows:

List<ISub<A>> list = new List<ISub<A>>();
list.Add(new Sub<B>());

You need an interface because only interfaces can have covariant or contravariant type parameters.

like image 125
Sven Avatar answered Sep 26 '22 02:09

Sven


Depends on how you use it, but perhaps you could use a covariant interface for Sub:

interface ISub<out T> where T:A
{
}

Then ISub<B> can be implicitly converted(via a reference conversion) to ISub<A>

like image 31
CodesInChaos Avatar answered Sep 26 '22 02:09

CodesInChaos