tags:

views:

243

answers:

9

Hi.

I honestly do not know what they are called. I have been unable to find articles on the internet.

So I understand that you can do something like this:

public struct Pair<T, U>
{
    public readonly T Value1;
    public readonly U Value2;

    public Pair(T fst, U snd)
    {
        this.Value1 = fst;
        this.Value2 = snd;
    }
    public override String ToString()
    {
        return "(" + Value1 + ", " + Value2 + ")";
    }
    public Pair<U, T> Swap()
    {
        return new Pair<U, T>(Value2, Value1);
    }
}

It could be a class instead of a struct as well.

But I am confused, for what purpose? Some kind of performance gain? As far as I understand, you can use these things (sorry, what IS the name of this?) to hold values. But wouldn't you always know what kind of data it should hold? For example: if you have a product you need to store, you just need to make a product class. Naturally you'd know what kind of data it needs to hold, since you are designing the code.

So yeah, I guess my question is: What is the purpose of this and what are the advantages over normal objects; which you'd specify a lot more

I think I am not being clear. I also want to know: is there ever a good reason to create something like the pair above? over, say, a more specific object, such as storing your product data in a product object, instead of some generic object that can take in everything.

NEW: Even more text: Also, how the heck can you handle error coding in something completely generic? I'd fear doing any kind of math manipulation or actually any kind of manipulation, when I have no idea what kind of datatypes I'll have to handle. If it requires me to write error-handling for all datatypes out there, then I REALLY can not see the advantages of these generic parameters.

+8  A: 

Suppose you had two situations where the code would be identical except that one of the types referred to in the code is different.

Wouldn't it be useful to be able to write the code out once, and then use that same code in both situations? For example, a container class like List - it should be clear that it would be a pain to have to write a different List class every time you want to store a specific type in it.

They are called type parameters, and a type that requires parameters is a generic type.

One very popular data structure is Dictionary<TKey, TValue>. It maps a key to a value, so you can look up the value for a given key. For example, the key might be "last name" and the value might be "phone number" - in which case both would be of type string (phone numbers are not always just numbers).

When looping through the contents of a Dictionary, each item it stores is a pair. In the standard class, the type is KeyValuePair<TKey, TValue>:

for (var pair in myDict)
{
    Console.WriteLine(pair.Key + " maps to " + pair.Value);
}
Daniel Earwicker
hmm but what about this pair forexample. Would there ever be a good reason to use this pair to hold data? I can not see one.
CasperT
Return two values?
Dykam
Sometimes you want to store a pair of strings, sometimes a pair of numbers. Do you want to write almost the same class definition twice? Maybe if you like typing (and fixing bugs in two places)!
Daniel Earwicker
@Dykam the question is not why you'd want to store two values, but why you'd want to make that concept generic and reusable for any pair of types.
Daniel Earwicker
maybe you have a name and a value: think about Pair<String, Int> ("Age", 30)
Francesco
@Francesco - same again: the question is not about why a pair is useful, it is about why generics are useful.
Daniel Earwicker
For some discussion about the use of a generic Pair class, see http://stackoverflow.com/questions/156275/what-is-the-equivalent-of-the-c-pairl-r-in-java/156685#156685
Luc Touraille
Thanks for the article Luc Touraille :) If you write the link as an answer, I will upvote it.
CasperT
The ideas in that article aren't very persuasive to me. And fortunately not to the designers of most languages, which have a general notion of a "tuple", a pair being a tuple with two values in it. The next version of the .NET Framework has a generic tuple class, and so does the next C++ standard.
Daniel Earwicker
One more question Earwicker :)You'd only use a generic parameters if you really feel it might be needed. It is always better to strongly specify, is it not? or is that just a common misconception.I can not see how you can prepare code for error-handling if you have no idea what the parameters will contain
CasperT
Is it better to strongly specify? So you should hae an `Add1(x)` function as well as `Add2(x)`, `Add5(x)` and `Add42(x)`? Or is it better to write one *general* function which can handle all of these cases? Usually, you want your code to be general. If you have a pair of values you need to pass somewhere, and there's no clear behavior associated with them, then why not put them in a simple pair class? And why should the pair class be hard-coded for *those* two types? Why not allow it to be reused?
jalf
I'd say the opposite, it is better to specify *as little as absolutely possible*. If there is any possible way in which I could avoid specifying something in code, then I shouldn't do it. That way my code becomes as flexible and generic as possible. Obviously, if I need to represent something specific like a product, then yes, I *have* to specify its behavior. There's no way around that, and there shouldn't be. But when writing a List class, why should I have to specify what type of objects it stores? It should be able to store whatever I need stored.
jalf
@CasperT - why do you think error handling code is special? By the way, you are correct that you cannot do much with an an object if you don't know anything about its type (at least in .NET generics). You can copy it (assignment), you can compare it with another object of the same type, but you cannot call any methods on it. This is where constraints are needed: by writing `where T : IThing' you allow the generic code to call the methods in `IThing` on objects of type `T`. But containers like `KeyValuePair` don't need constraints because they don't call any methods on the objects they store.
Daniel Earwicker
Thanks. This clarifies a lot :)
CasperT
+1  A: 

This is called Generics and the types represented by T, U etc. are called type parameters. The represent real types so that the compiler can statically check whether your code is correct from a type viewpoint.

See this introduction to generics.

Mark Seemann
+3  A: 

What you're looking at here is a typical definition of a container known as a "pair" (check stl pair or std pair).

Pair is a container that can only hold 2 values. Those values can be of different types.

for instance :

Pair<int, float> p = new Pair<int float>()

would create a new container that holds an int and a float :)

In your case T would become an int and U would become a float. It's a really simple template definition to be honest.

As far as your comment whether pair is used to hold data in the real world - heck yeah. Check out map containers - they use a LOT of pairs :)

Maciek
A: 

These are generic type parameters, which allow you to define the concrete (instance-)type of a generic class.

Have a look at this MSDN article for an introduction to generics.

M4N
+1  A: 

The word you are looking for is "generics". They allow you to specify that you will refer to a type, which you don't want to specify and will refer to by a label (eg: T). Imagine that you want to write a class which contains an Int. Then you need also a version for a Double, or which contains an object of some class of your own. Instead of writing n versions of this things, you simply let unspecified the name and then when you instatiate the object, you will specify what T will stand for.

Francesco
+1  A: 

It's called Generics. T and U are the generic parameters. I guess T for type, and U is just the next letter in the alphabet.

It's used for several things: improving performance, allowing the compiler to catch more errors, and making the code clearer.

In particular the standard library has generic containers that allow you to specify what they contain.

Pair can, for example, be used to return both the key and value of an entry from a map.

Douglas Leeder
What do you mean by: allowing the compiler to catch more errors?
CasperT
If you wanted to store "anything" then you have two options: either have a reference of type object (you can put anything in there) or a generic type (you can put anything in there but you have to specify the type, that's called 'parameterizing' it). If you choose the first option, you will have to cast your thing to an object type before putting it into your variable and cast it back to the type you expect when you get it out. If you make a mistake (you or someone else put in something that cannot be casted to the type you expect) then you get a cast exception.
Joe
A: 

It's a generic structure. Rather than design a class for every type of Pair that you would ever need, you define a single class, using generics, that operates on all types of pairs. This allows you to keep your code DRY -- rather than rewriting the same code for each possible type of pair, you write it once and reuse it.

tvanfosson
+4  A: 

Those things are called Generics and their purpose is to help you generalize algorithms, containers and methods without the performance overhead of casting the values at run time.

In the Pair class for example, think about your alternatives:

A. you could write a class that holds two Objects (as all the containers prior to .Net 2) but then you'll have to box or cast your types in order to use it and you won't have any type safety.

B. your other option is to write a specific Pair class for each type, which can be hard and not so wise to do. (take a look at StringCollection for example).

Now, imagine that you could write a class that could take any type without the performance overhead. wouldn't it be nice? In general, by writing Pair<U,T> you tell the compiler to generate specific Pair class for each usage. writing Pair<string, int> will make the compiler generate a specific Pair class for those types.

Note: C# generics are working somewhat differently from C++ Templates and the "workings" of the C# generics I described here is not exactly whats going on. It's just easy to understand it that way, I think. you can read more about the subject here.

Moshe Levi
+5  A: 

The purpose is genericity. Often, you have a class whose behavior does not really depend on the type it's used with.

Rather than Pair, consider the .NET class List<T>. It stores lists of... some type. The list doesn't, and shouldn't care what type it stores. It just has to guarantee that only that type can be stored.

A List<string> allows me to store strings. A List<int> allows me to store ints.

If we didn't have generics, we would have to either throw away type safety, and use a single List class which just stores Object's, but then there would be nothing to prevent me from storing an Apple in a list of Bananas.

Or we could write a new List class for every type we need to store. We could have ListOfApples, ListOfBananas, ListOfInts and so on.

I think generics offer a nicer solution.

The Pair example might be a bit less obvious, because often, if we need to store precisely two values, it's because they have some clear relationship which should be represented by creating a specific object. But sometimes, they don't. Sometimes they are just "the first value" and "the second value". Perhaps you have a function which simply returns two values. It's easier then to return a Pair<T1, T2, than to return one value and handle the other by having an out parameter.

You often don't need a pair, no. But if you really need "a way to store two values of different types inside a single object", if there is no real behavior associated with it, then a Pair class represents that nicely. And then why not make it reusable by allowing the types to change?

Also, how the heck can you handle error coding in something completely generic? I'd fear doing any kind of math manipulation or actually any kind of manipulation, when I have no idea what kind of datatypes I'll have to handle. If it requires me to write error-handling for all datatypes out there, then I REALLY can not see the advantages of these generic parameters.

Simple: .NET doesn't let you do that. In your Pair example, the compiler will complain if you try to use a function on it which is not guaranteed to be available. In your case, you'll only be able to use the functions defined on the Object base class (and of course, generic functions and classes which also work on any type).

So you can't use any kind of math manipulation on these generic types. You can't do much more with them than storing them, and passing them around (and calling .ToString()). But sometimes, you don't need anything more than that. For example if you're just creating a List class, or a Pair.

You can also specify constraints, narrowing it down a bit. For example:

void DoStuffWithStream(T arg) where T : Stream
{
  // in this function that T is some type derived from Stream, so we can use all methods that would work on a Stream.
}

This will produce a compile error if I try to call it with an int, but will work with all the various Stream subclassees. And now I know a bit more about the class, so I'll be able to do some operations meaningfully.

But going back to error handling, what errors would you need to handle in the List class? Not a lot of errors can occur. You have a class whose job it is to store a variable number of objects of some unknown (but fixed) type. It can insert new objects (which might throw an out of memory exception), and it can retrieve objects. It can let us search for objects, and then of course we might have the error case when the thing we searched for could not be found. But that's basically it. There is no error handling specific to the generic type. Why would there be? We don't do anything type-specific to the objects we store, so they don't really get an opportunity to throw any type-specific errors.

jalf