From the course: C# Essential Training 2: Generics, Collections, and LINQ
Understanding generics - C# Tutorial
From the course: C# Essential Training 2: Generics, Collections, and LINQ
Understanding generics
- [Instructor] In C# Essentials part one, we talked a lot about defining types. We defined those types with very specific plans in mind for how they'd be used. To start part two, I want to talk about generics 'cause this is a natural extension of defining types, but it allows 'em to be more flexible. Let's look at an example to help you understand why generics are important and why they were introduced into the C# language. Say I've got this method here called swap, and what I want to be able to do is have two objects or two references or variables and I want to swap them. Pretty simple, nothing too complicated there. So I take the second object, I assign it to a variable called temp, and now I point second at first and I point first at temp. As we're getting started, you may find some problems with this already and hopefully we'll come to that. Let's say I just want to try this with some simple types. I'll say x=5 and y=7 and those are just integers. And then I want to do Console.WriteLine. So I might use my string interpolation and I can say x, and I'll put x there and y and we'll put y there. So we want to put out those values. And in between then I want to call swap. Then I want to just pass not x and 5 but x and y into that method. This seems like it should work. So if x is 5 and y is 7. When we swap these and write it out, it should say x is 7 and y is 5, but it doesn't. Now if you watched C# Essentials Part One, you know why. 'Cause these are value types. And so when they go into this method and come back out of this method, they have different scope. We're actually copying values in there. Ah, you're thinking, let's use some reference types. Great. I have a person class that I've defined over here in my library. That library is referenced by my LinkedIn essentials program. And it's just a simple class called Person, first and last name and age and an ID. And of course you can grab these files from the exercise files and follow along. Now I've got some reference types. I should be able to come down and call swap on those. So I'll do Swap(p1,p2) and I want to swap those references. And now I can do a Console.WriteLine. And now I can do something like this or I'll say Person 1 and we'll do P1.FirstName. We'll just leave it at that. So if we swap these, we should then see that first name is going to be Amanda because we're swapping those two around. We'll run that again. Notice again we get person one is Matt. Why is that? Same reason we saw before with the value types. So again, you're thinking, well we'll add ref here 'cause this is going to allow us not to just change the parts of the object, but actually change what they point to. And of course we have to go back to the swap, we'll say ref here as well. And now we start running into some problems. We've got red squigglies. And if I go highlight that, it's going to tell me that it can't convert this from a ref of person to a ref of object. And the reason is a ref of object is very vague. That's kind of what we want here. We want this to be something that can point to anything, but that means I could pass in this person, but I could change it in the method to be an array or a date time or any other kind of object. And so the compiler's not going to allow me to do that. So we're a little bit foiled in our goal here. And this isn't actually the most ideal way to do this either. Even with our first example of swapping x and y, the problem was we're taking integers and we're treating them as objects. Now, C# allows you to do that, but it involves what's called boxing and unboxing and value type in state times can be treated as an object. That's a core principle of the language. But because they're treated differently in how the memory is allocated, it's an expensive operation. And this is where generics come in. What we want to be able to do is provide this swap method, allowed to use it with any type, but we don't want to use something like object. So what we can do is specify in our method this definition of a generic parameter called T, and that's a type parameter. So we're saying when you call the swap method, you're going to have to provide a type. And now instead of object, we'll put T here. And then inside the method, we don't want to treat it as an object here. Again, we want to set that as T. So let's go back up here to our person and we're just going to put that type, the person type in there and pass those in and write that out. Now for this swap, we could come in and do an int and now we can come in and say ref. And that's actually going to allow us from the compiler's perspective to do that. So we'd expect if we swap the people, is that P1.FirstName should now be Amanda, which was P2's first name, and x should be seven and y should be five. So we should see person one, Amanda, print out. And then we should see x is seven, y is five. And that's in fact what we get. So that one little change, just being able to specify dynamically the type for our method has made it much simpler for us to create a useful utility method or some sort of functionality. And then when we compile, it's the calling code that provides that type. So it's still going to get compiled in as that type. And we do know the type at compile time, so it can do all sorts of checks and other things that we would expect in our application. So these generic types as we'll see can be used not only on methods, but on interface definitions or class definitions as well.
Practice while you learn with exercise files
Download the files the instructor uses to teach the course. Follow along and learn by watching, listening and practicing.