Skip to main content

The evolution of C# Part II - Generics

This is a well discussed matter throughout the internet. Everyone knows about generics, what they do and what they are used for, right? No. There is a variety of reasons why you wouldn't know about generics, and some of them are:

  • You are new in the language
  • You are not new in the language but never cared to learn it
Simply because you never learned the basics about generics, it doesn't mean you've never used it. If you recognize this snippet, then you are already dealing with generics:


So, what is the advantage of generics?

Type safety
Generics will allow you to catch the errors at compile time rather than runtime by enforcing the rules of type safety that make C# a statically typed language. This leads to increased productivity because you don't have to run the code to know that something is wrong. For example, if in the snippet above you tried to add a new item of type string, a compiler exception would be thrown.

Typically, in C# 1.0, you would use an ArrayList collection to contain a collection of items, independently of the type. I think i never needed more than one type in the same collection, but ArrayList lets you create a mixture of different types. By providing the type you want the List to contain, the compiler will generate it for you behind the scenes and will recognize that in that instance you will only have int's.  Example:


The same would happen for Add, Remove and all the other generic methods of the List class. More on that later.

Performance
Performance is one of the main advantages of using generics in the situation described above. When you add an item to an ArrayList, you are performing a boxing operation (which means you are creating a special object and putting your value inside it), and when you retrieve it you need to downcast it to your type, performing and unboxing operation. This boxing/unboxing can become heavy when you do it multiple times like traversing a big collection.

By telling the collection which type it is dealing with you avoid that inconvenience of having to downcast your type from object in order to use it, and that will lead to better performance. Of course, the difference is only visible when you're dealing with big collections, but it is there.

Code Reuse
I think that this is the biggest advantage of having generics in your toolbox. When dealing with collections of items in C# 1.0, if you wanted to have the above benefits you would need to create your own collection. Imagine the overhead of manually creating a PersonCollection, BoatCollection, CarCollection, etc. Instead, we can now use generics for this daunting task! List(of T) does exactly that, so let's look at it's declaration:

The only unusual thing here is the T that comes after the name of the class. That is what allows us to pass the type that we are dealing with and is called a type parameter. Inside your generic class, you use T (or whatever name you give it) to refer to the type that the client code passes. When you create a List(of T), the compiler will create a class the way you would manually do. This means that you can reuse that code a lot more.

Let's explore the capability of Generics by creating a collection of our own:

As we can see, this is not a difficult concept to grasp. We create a new class called MyCollection which receives a type parameter. To this type parameter we will refer as T inside our class. We can see that we have a property called LastItem of type T which represents the last item added to our collection. We have also a method that receives a T and returns it after adding it to our internal collection and firing an ItemAdded event. Note that this event itself uses the type argument and a generic delegate meaning that it's second argument will be of T.

One thing to note in our implementation is that we are using generic constraints. These are the where T : Person that we see up there in the declaration. When we use constraints, the client will only be able to pass in a type that implements, or inherits, from those constraints. If Person is a class, then we will only be able to pass Person or a more derived type. Also, inside our generic class, we have access to the members in the Person type, because we know for a certainty that we are dealing with a Person. We can specify as a generic constraint the following:

  • a type
  • an interface
  • the special keywords class and struct
  • another type parameter 
  • new() This will let you specify that the type must have a public parameterless constructor.

This is how you would use the MyCollection class in a typical case:

We can see here that we used this collection combined with the Person type. After we specified the type, the compiler has all the information to create the class and analyze all the calls. The event handler is fired with the second argument of type Person, as we specified in the event declaration. The method AddAndReturnTheSame will receive and return a Person.

We can also have a generic method in a non-generic class, like so:


Note here that we are specifying the type parameter when we declare the method. There is no need to include this type when calling the method, because the compiler can do that for us inferring by the type of the parameter we are passing. This makes it simple for us to call the method without specifying the type parameters. We have the option specify constraints in this types too, if we may need.

What to use it for
A new namespace (System.Collections.Generic) has been created on C# 2.0 specially for containing the generic collections. List(of T) is one of the most used, but we also have a Dictionary(of TKey, of TValue) that you can use in almost the same way as you use an Hashtable (but with the above benefits) and also the whole base structure that supports this and other generic collections.

The whole concept of generics is more applied to collections in general, but that's not a rule. You can use it obviously wherever you want, including classes, interfaces, methods or even delegates. Using generics will provide more flexibility to your code, but can also reduce it's readability if you use it too much. Still, there are situations where i have applied it very successfully. The example i'm referring to was a user control that when clicked created a pop-up form. Using generics allowed me to reuse the code only by specifying some constraints. This way the User Control would never know the type of the Form, but could instantiate it anyway.

The default keyword
The default keyword has a very specific meaning in generic code. It takes a parameter which is the name of a type and it returns the default value of that type. So, if you pass it the name of a class it will return null, if you pass it a struct it will return a struct with all the fields initialized to the default value and so on. See the snippet:


Take a good look at this C# 2.0 feature and have fun coding!

Thanks.

Comments

Popular posts from this blog

The repository's repository

Ever since I started delving into architecture,  and specifically service oriented architecture, there has been one matter where opinions get divided. Let me state the problem first, and then take a look at both sides of the barricade. Given that your service layer needs to access persistent storage, how do you model that layer? It is almost common knowledge what to do here: use the Repository design pattern. So we look at the pattern and decide that it seems simple enough! Let's implement the shit out of it! Now, let's say that you will use an ORM - here comes trouble. Specifically we're using EF, but we could be talking about NHibernate or really any other. The real divisive theme is this question: should you be using the repository pattern at all when you use an ORM? I'll flat out say it: I don't think you should... except with good reason. So, sharpen your swords, pray to your gods and come with me to fight this war... or maybe stay in the couch?

The evolution of C# - Part III - C# 2.0 - Iterators

It's been a while since i wrote the last post, but i did not forget my purpose of creating a series that shows the evolution of C#. Today i came here to talk about one of the most useful features of C#, even if you dont know you're using it. Let's talk about iterators ! What is an iterator? For those of you who didn't read about the iterator pattern somewhere in the internet or in the "Gang of Four" book, you can read a description  here . The iterator is a class/object/whatever which knows how to traverse a structure. So, if you have a list or collection of objects, an iterator would have the knowledge of how to traverse that collection and access each element that it contains. The iterator is a well known design pattern and is behind many of the wonderful that we have nowadays in .NET (Linq comes to mind). Why is it a feature? Truth be told, an iterator is a concept well known way before .NET even existed. Being an OO Design Pattern, the iterator has

My simplest and most useful type

I have been doing some introspection on the way I write code to find ways that I need to improve. I consider this a task that one must do periodically so that we keep organized. There is a very, very simple problem that occurs in every application I know: How to return the results of an operation to the user? I've seen many implementations. Some return strings, some throw exceptions, some use out parameters, reuse the domain classes and have extra properties in there, etc. There is a myriad of ways of accomplishing this. This is the one I use. I don't like throwing exceptions. There are certainly cases where you have no choice, but I always avoid that. Throughout my architectures there is a single prevalent type that hasn't changed for years now, and I consider that a sign of stability. It is so simple, yet so useful everywhere. The name may shock you, take a look: Yes, this is it. Take a moment to compose yourself. Mind you, this is used everywhere , in every