Coding Shorts: Generics in C#

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi this is sean wildermuth it's time for another coding short this time i'm going to dig into generics now i'm old enough to remember when c sharp didn't have generics we were using arraylist for everything and doing all sorts of casts just to make everything work so i was a big fan of generics when it was introduced there's a couple of features in generics that i think some people miss they think about generics as just being about collections so we're going to talk about generics not only in collections but also in classes and methods and talk about inference and one of the things that i think might surprise you about generics and c sharp let's take a look [Music] so let's talk about generics and i want to talk about it in a few different examples because it may seem obvious if you're used to using generic collections that that's what generics are really about but there's a lot more going on than that let's start with net100 way way back in 2001 when i got started with csharp and net and there were no things like generics and so i've written this code a lot arraylist list equals new arraylist and what arraylist was and still is is a collection that is non-specialized it just allows you to have a collection of objects so if i say list dot add it's going to be some object value and in our case we can say 1 because of course that is an object and if i say add one here what's it going to do it's going to also box this as an object and so when we do for each we could do something like you know write line item here that will work but it only works because right line is going to treat each of those things that's being rightlined to as an object and calling tostring to get out of it right and we want something different and there were a bunch of code generators back then that allow you to create these type saved classes and was generating a bunch of code and so in net 2 it quickly said you know what we need generics generics are important and so this should be closer to what you've been writing probably for a long time which is a new list and let's say that is of string and let's bring in those generic collections and now we can see that we have the list of strings but of course it's not going to allow this because we're telling it what kinds of things we want to store in them the way that the for each works is still the same except that this item of course is going to be a string it's going to know it's a string because this is a generic parameter of the list class right and so of course this add one no longer works for us because it has to be a string and so if we were to do something like two here right it's a string just type checked and also when we get items out of it whether it's in the for each or looking at the array indexer or a bunch of things like that they're all going to know about this being the string because this is the type specifically for your use a list of string and so if you've done c sharp any amount of time you've done this this is pretty basic c sharp 101 sort of things that you were learning right but generics go way way beyond that so let's talk about using generics in your own classes so let's create a public class here i'm going to call animal let's say i just want to have a constructor that allows me to pass in let's say an integer for an id right and then go ahead and assign a field so we can get at it and we're all good right there's an essential problem here is in that it's assuming that the integer is the type of the id that i want to expose and so let's create a property here let's say we have an id here and that's great but in some cases you're going to want to be able to supply a generic argument here to say you know what i know i need an id but i don't know what type i need it to be different people might have different reasons for it so let's introduce t to our class and what is this t but a templated argument and so we can use this and remember this is a type not a piece of data but a type and so if we just replace t here let's assume that we can't set it i'm making this way harder than it needs to be return the stud id right what we're essentially saying here is that when you supply this you're going to tell me what kind of id i want to support this could be a good this could be an object that has more than one property that i'm not going to need to know about what that is ahead of time and more importantly when i have another class let's call it dog that derives from animal i can go ahead and tell it what the type is there sorry i need to say class here and so i'll need my own constructor for dog and i'll do the same thing i'll say string id and that string id means that i can just then pass it down to base id and that works because the call for calling the base constructor here is going to be a string because we specified it here this dog doesn't need to be generic for all of this to work now what if we wanted to really define what could be this right because we could certainly change this and let's say make this an exception right and then we'd need to return a new exception with some piece of data in it right of course exception doesn't make any sense for an id so we'd like to be able to smartly talk about what this can be and so there's a few different ways to do that but you do this with what's called generic constraints and so in our case we're going to tell it where t is what is i disposable right we're essentially telling it that whatever can be in here has to live up to some set of constraints of course this doesn't work because dogs gonna say string can't be used because there's no explicit conversion from a string to i disposable right it's assuming that this is going to be those rule sets that you really need now what if i just want it to be some object instead of a primitive type the sort of trick there is to say new instead of saying object here which could work what we really want to say is that we have the ability of being able to construct this with an empty constructor or with a constructor of some known type right the new is saying that we have a way to construct these if we don't have the constraint we can continue using things like string or int or whatever we want but we also have essentially a problem and that is what happens to this t when i want to be able to generate it so let's talk about that by talking about two different ideas here so one of the things that i find that i commonly use is generics on methods now we talked about a generic in this class but let's go ahead and just create a method outside the animal class and i'll just call this public t and i'll use that t again get value by the way the t isn't important here this could be t value it could be just value whatever you want it to be this is just a name so here i'm going to go ahead and say t value and let's go ahead and return some value so if we want to say return here and generate whatever the property here was that it wants to return i think i have to get rid of public here how do i do that i could say new t-value but this doesn't work and the reason it doesn't is it doesn't have a constraint that says that we can construct them in this way and so if we were going to use that constraint or t value is new then that would work right but without the constraint here it doesn't know what to do here and so another option here is to use default t value what this does is depending on what is being passed here is it can create a default version of this so we don't need the constraint so this is an integer you're going to get a new integer of zero this is a string it's going to be an empty string if it's a object that has an empty constructor it can create that otherwise you'll get a runtime error but in this way we can generate the new values just as well and again we can continue to use constraints to sort of handle that and so we look at let's say val call getvalue and say we want a string what happens this vowel the return argument is going to end up being a string this is an object same thing you're going to get returned an object and if this is an integer you're going to get an integer right so we're able to do that sort of thing but another notion or another strong use case for generics inside of methods is this interesting notion of implying the type so if i say that we're going to pass in a t value whatever this value is and let's call it our value and i know this doesn't really change anything but we're just going to return the value right we don't do any real work here but maybe we did and so this is going to expect a value so if i wanted to be int i could put 1 there and of course that works right this is going to return actually that one back here in value what's interesting is that c sharp can infer that so by saying get value one here goes okay you've passed me a one that passes here so you must mean that this needs to be an into value here an inch value here of in value here so if i put a a new dog here what happens what do we get back here in the value we get a dog right because whatever we're passed in here we're gonna get back out that same type and so this can be a very powerful idea here imagine if you need to parse out some piece of information and you want to get it out what you'll often see is an object get value let's say some sort of key here and then they need to return list key right they're going to return some object that they're getting from this list and this is pseudocode so it's not going to work and what does this look like when someone's actually calling it this way i'm just going to call it guess we don't have any confusion here so i'm going to go ahead and get x because i'm running out of names i can come up with the top of my head and let's call get with hello but in order to turn into what i really need let's say if i know it's a string then i end up having to cast it right and let's just say we're going to return the first one there just to get rid of the idea so this works because it assumes that this is going to return us a string and maybe it's something we know about but more importantly if we want to use the generic argument we can go ahead and say t here get the key and then just say as t right whatever is returned here i'm going to try to cast it of course this doesn't work for the constraints because this could be a class so instead of as which only works on reference types let's go ahead and just do t here right and what does this mean this isn't a lot better but it does mean that you can be very specific and i think this reads a lot better than the casting the casting also is sort of hidden in here by saying what we want it to be the last thing i want to talk about are lambdas and how generics play a role here so if i want to write a lambda let's just call it f for function and i want it to just run some operation like right line one right and then later on i should be able to call it as f but i need to tell it what this actually is it can't implicitly create this because i need to create an action or a func now action has no return value but funk does and so that's the big difference between those so i'm going to say action here and what am i going to tell it that our action has no parameters right because we don't need to specify a argument if there's no parameters being passed to it but what if we change this and say action string right and it's going to complain here because it's going to expect this to be some value and then use that value here so i then can say hello and this function works because it knows that it's expecting one string argument here and that's kind of how actions and functions work so let's copy this one more time and let's create it as a func just so you can see the difference here so in funk the number of parameters you're going to use are at least one now in the case of func string what that actually is assuming is that you're going to have no parameters but you're going to return something in our case like a string right and the chief idea behind the function using these generic parameters is to specify the input as well as the output types if there's just one argument in funk it's the output type but if there's two let's say integer and string it means it's going to return a string but it's going to expect an integer in our case that y should be the integer here well what happens if we have integer string string right then it's going to expect that the arguments are going to be id and name because these first two arguments are specifying that this is going to be an int this is going to be a string and that it's going to return a string that's what that last parameter is always there for so z equals g 5 bob right and so we can now use this func just like we could create a local function but of course you can pass around and do some other things that aren't possible but we can now see what's really happening here is we're using generic parameters to specify what the lambda signatures are and you're going to see this happen quite a bit especially if you're going to allow people to pass in a lambda that you then execute that's going to be a pretty common use case so hopefully you've gotten a sense of where generics matter more than just in the simple generic collections we're going to see that the usefulness of using generics in creating generic classes generic methods and then of course lambdas that we're going to start to use the real power of what generics are really about thanks for joining me on this coding short my name is sean wildermuth see you next time you
Info
Channel: swildermuth
Views: 1,145
Rating: undefined out of 5
Keywords: C#, .NET, Programming, Software Development, Generics, Collections
Id: u_YyL8ZOWFU
Channel Id: undefined
Length: 15min 12sec (912 seconds)
Published: Thu Apr 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.