What Is Cool About Generics, Why Use Them

What is cool about generics, why use them?


  • Allows you to write code/use library methods which are type-safe, i.e. a List<string> is guaranteed to be a list of strings.
  • As a result of generics being used the compiler can perform compile-time checks on code for type safety, i.e. are you trying to put an int into that list of strings? Using an ArrayList would cause that to be a less transparent runtime error.
  • Faster than using objects as it either avoids boxing/unboxing (where .net has to convert value types to reference types or vice-versa) or casting from objects to the required reference type.
  • Allows you to write code which is applicable to many types with the same underlying behaviour, i.e. a Dictionary<string, int> uses the same underlying code as a Dictionary<DateTime, double>; using generics, the framework team only had to write one piece of code to achieve both results with the aforementioned advantages too.

Is there any reason to use generics in Java?

Well, if you don't use generics, you get to cast each time. You would have to:

// if raw List
MyClass c = (MyClass) myClassList.get(0);
// if List<MyClass>
MyClass c = myClassList.get(0);

for instance.

Yes, generics are erased at runtime, yes, they are here to enforce type safety at compile time only; however there is still runtime type erasure when you use bounds. Example:

public <E extends RuntimeException> E get(final Class<E> c,
final Throwable t)
{
try {
return (E) getHandle(c).invokeExact(t);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable oops) {
final RuntimeException exception = new IllegalStateException(oops);
exception.addSuppressed(t);
throw exception;
}
}

The E here has a runtime type erasure; it extends RuntimeException. Therefore the cast is to RuntimeException, not Object.

See the javadoc of Collections.max() for another interesting example of runtime type erasure (hint: why does it define T extends Object & Comparable<? super T> instead of T extends Comparable<? super T>?)

What are the 'good' reasons to use ? in Java Generics?

Any time you could use generics but don't need it in that specific situation. <?> tells the compiler roughly: "I know about generics, but I don't need the type now".

Maybe the type is needed in other situation. E.g. if you have a Set that just stores anything, like a cache, and you just don't care for the type of the elements at all. At other times you do, when you process specific elements.

It smells if you use too loosely bound type parameters (like <?> which is quite loose) but try to determine the type afterwards, e.g. with instanceof or some custom type discriminator. Then something was designed poorly.

Most important things about C# generics... lesson learned

One of the most important things I've learned is that you can constrain the generic type parameter(s). This can be very powerful, allowing you to take customize the class for only certain types of objects and allowing you to use the members of that type in your generic class. I realize that this is pretty fundamental, but it's one of the things that makes generics incredibly useful.

Understanding C# generics much better

A very simple example is the generic List<T> class. It can hold a number of objects of any type. For example, you can declare a list of strings (new List<string>()) or a list of Animals (new List<Animal>()), because it is generic.

What if you couldn't use generics? You could use the ArrayList class, but the downside is that it's containing type is an object. So when you'd iterate over the list, you'd have to cast every item to its correct type (either string or Animal) which is more code and has a performance penalty. Plus, since an ArrayList holds objects, it isn't type-safe. You could still add an Animal to an ArrayList of strings:

ArrayList arrayList = new ArrayList();
arrayList.Add(new Animal());
arrayList.Add("");

So when iterating an ArrayList you'd have to check the type to make sure the instance is of a specific type, which results in poor code:

foreach (object o in arrayList)
{
if(o is Animal)
((Animal)o).Speak();
}

With a generic List<string>, this is simply not possible:

List<string> stringList = new List<String>();
stringList.Add("Hello");
stringList.Add("Second String");
stringList.Add(new Animal()); // error! Animal cannot be cast to a string

Practical uses of generics in .net (Besides the ones in the framework)

I'm using generics every time I need to apply same algorithm / same logic on different types of objects.

Example is generic repository:

public interface IRepository<T> where T : class, IEntity
{
IQueryable<T> GetQuery();
void Update(T entity);
void Insert(T entity);
void Delete(int id);
}

public interface IEntity
{
int Id { get; set; }
}

What are generics in C#?

Generics refers to the technique of writing the code for a class without specifying the data type(s) that the class works on.

You specify the data type when you declare an instance of a generic class. This allows a generic class to be specialized for many different data types while only having to write the class once.

A great example are the many collection classes in .NET. Each collection class has it's own implementation of how the collection is created and managed. But they use generics to allow their class to work with collections of any type.

http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx

Why not always use Generics?

In general you should - however, there are times (especially when writing library code) when it is not possible (or certainly not convenient) to know about the calling type (even in terms of T), so non-generic types (mainly interfaces such as IList, IEnumerable) are very useful. Data-binding is a good example of this. Indeed, anything that involves reflection is generally made much harder by using generics, and since (via the nature of reflection) you've already lost those benefits, you may as well just drop to non-generic code. Reflection and generics are not very good friends at all.

Why/when should generic methods be used?

Generics, among other things, give you a way to provide a template -- i.e. you want to do the same thing, and the only difference is the type.

For example, look at the List API, you will see the methods

add(E e)

For every list of the same type you declare, the only thing different about the add method is the type of the thing going into the list. This is a prime example of where generics are useful. (Before generics were introduced to Java, you would declare a list, and you could add anything to the list, but you would have to cast the object when you retrieved it)

More specifically, you might want 2 ArrayList instances, one that takes type1 and one that takes type2. The list code for add is going to do the same thing, execute the same code, for each list (since the two lists are both ArrayList instances), right? So the only thing different is what's in the lists.

(As @michael points out, add isn't a true example of a generic method, but there are true generic methods in the API linked, and the concept is the same)

Why are generics needed when we can do casting to Object class?

I can make a list in the "pre-generic" way and do something terrible like this. The result is I can't know the type of the object I get from the list without resorting to reflection.

List myList = new ArrayList();
myList.add(new Integer(1));
myList.add(new Cat());

Object whatIsThis = myList.get(1);

With generics, I can say

List<Cat> myList = new ArrayList();    
myList.add(new Cat());
myList.add(new Integer(1)); // compile time error
myList.add(new Dog()); // compile time error

Cat whatIsThis = myList.get(1); // I *know* this must be a Cat


Related Topics



Leave a reply



Submit