Get Func-y: Delegates in .NET - Jeremy Clark

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay it's after lunch this is the best to have because I know you right now I'll try to be as entertaining as possible I'm here to talk about delegates and the reason I talk about delegates is because it's one of those things that was difficult for me to learn as a developer but once I finally got it I'm like these things are really awesome they're really useful so I try to help people get over that hurdle we're going to be looking at kind of some basics of delegates but then we're going to ramp up and kind of look at a lot of the features that are out there you know it's and just as a warning for those of you who don't know delegates are kind of a gateway into functional programming so if you're afraid of functional programming you might not want to sit around for this talk otherwise it'll make you excited so if you're looking for these slides you can go to my website Jeremy bytes calm and feel free to tweet it awesome things about me as I'm doing the talk if you'd like to tweet not awesome things about me please come talk to me about it because I'm always trying to improve so with that let's go ahead and get started now the first thing that we have a problem with delegates is kind of understanding exactly what it is so I start out with a definition that actually comes from the Microsoft documentation and a delegate is a type that defines a method signature that takes a little while to wrap your head around because if you're a c-sharp programmer and you're kind of used to well yeah I understand types you know we've got classes they've got properties and they've got methods and all these other things we've got structs value types we've got stuff like int and list of T and all that cool stuff there's I understand types but this isn't quite like those types instead of this being something that's like holding data and has functionality all it does is represent the signature of a method so it's something that we can actually assign to and later on we can invoke any methods that are hooked up to a delegate but it's it's kind of odd and like I said it took me a while to wrap my head around that now we might say well what do we care about delegates well there's a lot of cool features and there's a lot of places where we find them already one cool feature of them is the coupling code and we're going to be looking at that today so they actually allow us to kind of easily implement the strategy pattern which sounds a lot smarter than it really is what we'll see it's just like choosing what we want to do later it's kind of what that means it also helps us with because we can use methods as parameters and like I said kind of a gateway into the functional programming world these are what are known as higher-order functions where we actually have methods that take methods as parameters and it's actually kind of a cool thing now they have a cool capability which is called multi casting and I'll show you what that is because that's really cool and then also if you've ever used an event handler you've already used a delegate without even knowing it because event handlers are in fact just special kinds of delegates their delegates that have a few more restrictions on them and then the most awesome thing in c-sharp is link language integrated query I love link link is amazingly awesome I also love lambda expressions as you'll see as we go and the thing is you know we've got all these cool stuff that we can look at but we're not going to look at them in slides because I'm not a big fan of slides in fact that's my last slide it's that okay with everybody I love code I love showing things in code so we're going to spend the rest of our time in a visual studio now the first thing I'm going to do is wow you with my amazing UI development skills trust me just hang on to something come on visual studio I know you can do it I always get concerned when it like says rewriting component cache it's like didn't you do that earlier come on you can do it I'm pretty sure Visual Studio can do this so in the meantime I think I have some shadow puppets that I can do come on okay I like that much better so let me run this application before we look at what's inside of it because again I want you to be amazed at my UI skills now this is WPF because I love sam'l sam'l is an awesome UI development tool and as you can see on the left hand side we have a list of data items these are person objects which we'll see in just a bit and for those of you who have been like yeah it's been kind of a really long week so far and I'm kind of tired after lunch if you want to give up on the delegates talk I'll give you a little challenge figure out what my data set is but you're not allowed to use any internet-connected device for that so if you can figure out what my data set is please come talk to me afterwards because you're the kind of geek I want to hang out with but what we're going to do is we're actually going to work with this data by just doing some processing with it and we'll see how delegates work by doing this so you can see we've got some radio buttons here that we can pick and we're going to put some output data in that box on the left hand side we also have some actions with some checkboxes and right now this process data button doesn't do anything this is what we're going to fill in so first of all let's take a look at our data class which is called person and it's an amazingly simple class it has four properties and a two string method so it's just got the first name a last name a start date and a rating so that's just the shape of our data and then I've overridden the default two string so that we can kind of give a nice format if someone just is to string on this now what I want to do is I want to be able to output different strings you know different ways of outputting this particular class without having to go in and write a whole bunch of different methods inside this class and so the way I'm going to do that is by using a download now a delegate like I said is a type that defines a method signature so what I want if I wanted to for example have something they could do this to string I could write a method that takes a person object as a parameter and returns a string that's a pretty simple signature so I'm going to write a custom delegate for this just to start out with so I'm going to say public we'll make it a public delegate delegate and it's going to return a string we'll go ahead and call this person formatter and it will take a person as a parameter which will just call input so if you notice here I just have a method signature there's no method body all I'm saying is I'm creating this custom type and this custom type represents a method that takes a person as a parameter and returns a string now you might say what's the use of this well now I can create a custom to string method really really easily in my class so what I'm going to do is just create another two string here so we'll say public return a string called two string and this is going to take a person format or delegate as a variable so basically what we're going to do is pass a method as a parameter to another method now why do we want to do this well you'll see why we want to do this in just a bit for now inside the body of this method I need to run this method that's hooked up to it and that's known as invoking the delegate so I can say formatter invoke and then if you notice down here when we the parameter that they invoke once is a person object and that makes sense because again we need a person as a parameter and we're going to return a string here now since we're inside a person class I'm just going to use this as the parameter so you're going to use whatever objects that we're currently in and then again this does return a string so that means that we can just return the output of this for our two string method and so basically what we're going to do is run the delegate and turn whatever string that delegate method gives us back why would we want to do that I keep asking that question well let's do something with it so that we can see why now for this I'm going to flip to the code-behind of our form just to keep things simple I just have everything in the code behind so that we can focus on delegates and not necessarily you know gigantic cool architectures for complex applications and you can see I have this process data button underscore click event handler here and right now it's just clearing that output list box so what I want to do is I want to use that to string method but in order to that use that to string method I'm going to need something that matches that delegate well first let me go ahead and and a put in a for each loop here so I'm going to loop through each person in our list box so we've got the person list box type items and then I have this add to list method which we can see down at the bottom which will just add items to our output list and this wants a string so I could say person dot to string and that would just give us the default to string method on the object but we have an overload that says hey we can pass in a person formatter variable here okay how do we pass in a person formatter all we need to do is create a method that matches that method signature so up here I'm just going to create a private method that returns a string so again it has to return a string take a person as a parameter I'm going to call this output last name it's going to take a person add as a parameter input and then we're just going to return input dot last name are you guys horribly impressed with my coding skills yet trust me it does get better I hope so now that I have this I can actually call I can actually pass this method to my to string method that I have down here so I'm going to loop through all the items it's going to call a two string method passing in this other method that says here's what you want to do with this and if I run this right now and click our process data button you can see we have the output that's showing that now that's not really impressive because this is kind of hard coded at compile time and if you notice I have some radio buttons there and I'd really like to hook those up so I can change behavior at run time so let's go ahead and head that direction so what I'm going to do is create a variable so we'll then put this at the top which is of type person formatter so again that's our delegate type and I'm going to just call this variable formatter so what this is is this is now a variable that I can assign methods to as long as they match our delegate signature so again take a person as a parameter return string so that means down here in my code rather than using output last name directly we can say formatter equals output last name so again assign it to the method we want to use and then pass that variable in now this isn't real exciting all I did was create an intermediate variable but what we can see is that our code still behaves the same way at this point but now that I have that intermediate variable it would be real easy for me to just figure out that I want to find one of four or five six seven different methods as many methods as I'd like to it so in this case I want to create some methods that we can use so I'm going to add a new class and we'll call this formatters and this will be a public static class and it will have some public static methods in it now these public static methods will need to match our delegate signature again take a person as a parameter return a string so we'll create a public static method that returns a string I'm just going to call this one default pass in a person and this one you guys are going to be really impressed with this this is just going to call the no parameter to string message Wow I see a lot of really excited people out there yeah there's at least one now lucky for you you don't have to watch me type the rest of these unless you want to watch me type anyone once we type C the thing is if I have to type big blocks of code I'll start to tell really bad jokes and you guys really don't want to hear that so what I've just pasted in is a set of four methods that all match our delegate methods signature so we can see they all take a person as a parameter and they all return a string but they all do something from slightly different so again that first one there we're just going to do the default that's on our person class the second one here called last name to upper that upper case is the last name hopefully that's kind of self-explanatory first name to lower we'll go ahead and lower case the first name and then I have full name down at the bottom and this will do last name comma first name and so that's okay for most Western names for Eastern names that doesn't work out too well but I'll leave localization up to you so now that I have these four different methods that match the method signature I can assign any one of these to my delegate variable that I have and what that means is I can hook that up to the radio buttons that I have in my UI and this is where things start to get really cool so I'm just going to create a little method here private void called assigned delegate and what we're going to do in here is we're just going to assign one of these values to the formatter variable that we have now again I won't make you watch me type in all this code unless you want me to anyone yeah thank you and so basically what I'm doing is I'm looking at okay apparently I need with something different fine actually I like format person better I'm going the other way okay so what I've done and this assigned delegate is based on the various radio buttons we have so I have a default string button a last name string button the first name string button a full name string button based on that I'm just going to assign one of those formatter methods to my delegate that I have here you guys following me so far this is where things now start to change at runtime because instead of assigning this format person directly to this output last name method that I have here I'm going to call a sign delegate and what that will do is that will look at the state of our UI elements and decide which thing we want to do in fact we'll go ahead and just get rid of that output last name completely now when I run the application will see that our radio buttons actually work so if we click on the process data button the default again is the default to string that we have on the person class if I click on the last name now we get the last name to uppercase first name is first name to lowercase and full name is last name comma first name that starts to get really interesting when we think about what's actually happening here because if we go back to our code and look at our person class what this has given me the ability to do is change the behavior of my person class without having to change the person class itself it's given me an extensibility point and if you're one of those solid design principles people this is an example of the open-closed principle it's open for extension but closed for modification so I can change how this class displays itself when I call to string without having to change the class itself now this class is pretty simple but we could also argue that this is an example of the single responsibility principle as well because we could say okay what's the responsibility of this class what is its reason to change well it's not doing much right now granted but probably its primary responsibility is holding the data holding those fields that it has its responsibility isn't figuring out what format it should output itself in that should be somebody else's job so this gives us a really easy way to do that and when I first saw this I'm like this is really really cool Wow and then I think I mentioned that I might talk about the strategy pattern this is a very simple implementation of a strategy pattern too so if you're one of those people that are looking for those kinds of elements and saying oh that's curious maybe I can use that in the future delegates are a really awesome way that we can get there now if you notice I created a custom delegate now you probably didn't notice that but my custom delegate is called person formatter and that's actually a custom type that I created just like my person class is a custom type that I created but I don't have to create custom types for delegates because the dotnet framework has these really awesome built-in delegate types called funkin action has anyone seen func well yeah I'm sure you have so func is awesome but the first time you see it you're like I have no idea what this thing is so I'm going to go to help because I read documentation for some reason I'm just going to type in func of T well grab this one func of TT result and all this is it's a built-in delicate type that uses generics so if we look at this we'll see how func of key T results now T is the argument it's kind to tell but those are just parentheses so there's t argh that's the parameter that this method takes and T result if we can see is actually the return type that's coming back from this funk so basically this can represent any method that takes one parameter and returns a results that means that I can get rid of my custom delegate type and use this one instead now before I do that I want to show how related these are I'm just going to copy this code and paste it right underneath my custom delegate and then get rid of some of this white space here and just show how these things line up because again the first time I saw func I was like yeah I'm not exactly sure what this thing is but it's just a custom delegate or a built-in delegate I should say that has generics so we can see our instead of having string we have T result so again we can put in whatever type we want there and then for the parameter instead of having person we have T and so that means that we can pick any type that we want for that so that means is instead of creating this custom type I can use this built-in one and that's what I'm going to do I'm just going to delete a custom delegate type now you'll notice my two string method is no longer happy but all I can do is replace this with func of person string and this has the same method signature so again looking at the two generic type parameters that we have there the first one is the parameter so again person is the parameter the last one is our output so that's our string coming back from it now notice nothing else in this code is complaining it's like that's fine take a person as a parameter return a string I totally understand that how much code do we need to change on the calling side well it turns out not much this person for matter field that I have here he's no longer happy because this custom type doesn't exist but if I change this to a func a person string now everybody's happy again and I don't have to change any of the other codes so I can rebuild I can rerun the application and we'll see that it behaves exactly the same way so there's our last name or our default our last name - upper first name - lower and the full name so it still all works exactly the same way now there's a couple things that I like about using funk I mean there's nothing that stops us from creating custom delegates but funk is built-in so I like to use stuff that's already there if I don't have to create something that's better there's also something that's a little I don't want to say esoteric but if you have to custom delegate types even if they have the same method signatures you can't directly assign them to each other you have to do some casting and taste Andrew knows how to do that because he was just showing you that in the case of funk I can assign anything to this that matches this method signature so again it takes the person as a parameter returns a string and that's why all of our stuff still works now from a practical standpoint as a programmer I really like this as well because let me come back down to this to string method now if you remember before when I did my little pop-up to say hey what parameters does this to string method take well before it said this takes person for matter if I don't know what that is I have to go look it up I have to say Oh person formatter takes a person as a parameter returns a string but if I look at it when it's using funk right here it says this is a funk of person string that gives me all the information that I need in order to use this function because it's like okay I just need a method that takes a person as a parameter and returns a string so I have all the information here and I love when code is obvious I hate I hate code that hides its intention so I really like this now the cool thing about what's built into the the framework is that there's more than just this funk of TT result there's also funk of t1 t2 t results so this takes two parameters and has a return type and then it keeps going in the dotnet 3.5 world we were limited to this right here which is a funk of t1 t2 t3 t4 t results so we could have four parameters and a return type now these ins and outs that you see here these technically has to do with covariance and contravariance which I'm totally not going to talk about today and that's in the generics world but I use these as a little clue to say is this a parameter going in or is this a return type coming out so you can look at the signatures and see that now someone decided years ago that 4 parameters might not be enough so we want to have more and so in dotnet 4.0 we actually got this one I really love this one this represents a delegate that takes 16 parameters okay here's a clue if you have a method that takes 16 parameters please please PLEASE ask a friend to look at your code I would not recommend using this now I was really hoping that in dotnet 4.5 I could have one that takes 64 parameters but apparently someone decided 16 was enough so anyway the correct number is I don't know how much so we don't have to just have one parameter coming in in order to use funk we can use it for a variety of different situations now if we look at what we have here in it so has anyone figured out my data set yet don't shout it out you'll give it away I'm going to ask you how many of them you actually know how many do you know - there's seven of them out there anyone know more than two okay talk to me afterwards so we've seen that we can easily swap out things at runtime we can change the behavior of a class without changing its code I love that kind of power now you might say are we going to get into trouble like abusing that power well if we look at the class that we have there's really not much that we can do with it because what we're doing is we're saying okay this is going to take a person as a parameter technically whatever we pass in is allowed to modify that object so it can change the properties of the person class if it really wants to but if you notice this particular class all of all of the members are readwrite so they all have public setters and public getters so you can change all of those anyway now if you're more concerned about you know am I am I able to change the things that are coming in here there's ways that you can get around that so if I were to create for example read-only properties have a constructor to populate those then I could actually make a copy of the object and make sure that you're not modifying anything directly but in this case this will work for what we have now when we look at the invoke here we are going to add a little bit of exception handling in a bit but there's a shorter format that we can use for this instead of calling invoke we can just put parentheses directly after the delegate itself and that will execute the method now there's times you may want to use this in times that you want you may want to use invoke and we'll see that in just a bit and it's more for semantics purposes but this works exactly the same way it will still invoke the delegates and run the method that's associated with it okay so let's move on to the other part of the UI that I have here this is where things get this is where you have to start thinking and it's really cool what you have to start thinking about because if you notice I have this action section here and it's a set of checkboxes and so if we look at the actions I have average rating okay so it needs to go through the items in the list and figure out if you'll notice there's like 6 out of 10 stars 8 out of 10 stars I want to take that rating value and get an average for it for everything that's in the list for the earliest start date I want to go through the list and you'll notice these all have years associated with them and I want to pick out the year that is earliest chronologically for the best commander I want to go through the items in the list pick out the one with the highest rating and display that person's name and then for first letters what I want to do is I want to go through the items on the list pick out the first letter of the last names and output those to the screen so if you notice I want to perform some kind of operation based on the list itself now for this I'm not going to have any return values instead what I'm going to have is methods that just return void but take a list as a parameter so let's just see how would I create a custom delegate for that well again I could say delegate void again it returns void and we'll call this person action and this takes a list of person as a parameter which we'll call input so if I wanted to create a custom delegate this is the signature that I'd want to use and again I could take the list loop threw it out put stuff into my UI my UI output box but instead of doing that I want to use another built-in delegate type and that is action of T now func of T and action of T are closely related as you might guess action of T is a built-in delegate that returns void so rather than you're returning a value it performs some type of action and we can see I've got a parameter here so returns void takes a generic type as a parameter so again we can use this however we'd like now again in the.net 3.5 world we did have up to four parameters available and for you brave souls who are writing really hard to read code you can't have sixteen parameters for action as well and so this is where things start to get interesting because we're going to have some nested generics and those kind of frighten me a little bit especially the first time I saw this that's why I wrote out this custom delegate to start with so this is going to be an action and we're going to go ahead and call this process people but I do want a parameter for this okay now the parameters coming in is a list of person so I want to have an action of list of person I love nested generics it's even better when you start using tasks because like a tasks continuation has a parameter which is a task of action of list of person the way that I use it so yeah nested generics are really cool so it does take a little while to wrap your head around this but remember kind of the outer angle brackets that we have there just say okay these are the parameters inside and then the list of person just has its own generic type along with it so let's go ahead and get rid of this custom delegate because again we can just use this class level field that we have and I want to hook up some methods to this as well now before that I'm going to do a little bit of housekeeping because this code that I already wrote I only want this to run if our string expander is open so if our string expander is expanded go ahead and run this little block of code that you already ran and then if our action expander is expanded we'll go ahead and do something else and so what I want to do is basically kind of go through the same process that I did with our funk I want to go ahead and create a method that will go ahead and assign whatever we want to our action delegate that we have so I'll go ahead and create another method here called private void assign action and I'm going to start out really simply by just assigning to this process people variable that we have now one thing that I love our lambda expressions does anyone here love lambda expressions does anybody here hate lambda expressions that few people Wow if you hate lambda expressions I have a video on my website called learn to love lambdas and so you should go watch that like immediately because lambda expressions are awesome and if you go to my website and follow the links for the materials for this top you will find that there okay so I'm just going to use a lambda expression here to get B I'm just going to do the first one which is the average rating that we have for all of the items that we have on the list so this is fun I'm going to say P goes to oh did I leave you already P a bridge R goes to r dot rating and then we'll say dot to string and then I want to put this in the output box so I'm going to wrap this whole thing in an add to list Wow okay when I go lambda expressions I go lambda expressions hard well let's see what this does so let's go ahead and collapse our string Handler and expand our action now I'm not hooked up to any check boxes yet in fact I'm not even calling this method yet am i calling this method would probably be make things work a lot better so can call the assign action and then what we'll want to do is also invoke that delegate right so we have the person formatter delegate that we want to or I'm sorry process person process people man apparently I didn't get enough lunch we have our presses people a delegate that we want to invoke and again if we look at the parameter that this wants it wants a list a person as a parameter well I have a little method that will get me the collection of person objects so I can save our people equals people get people and so that give me a list of person objects that I can pass through here people there we go so what I'm doing is I'm calling a sign action and that will assign this add to list this P goes to add to list to my process people delegate variable that I have and then down here we're going to go ahead and invoke that delegate based on this people collection that we have does anyone have any idea what this might do nobody at all this is a quiet room don't make me tell jokes so I click the button and I get the average rating for my seven items that I have here with a lot of decimal places but here's something that's interesting because if I click the button again now I have two of them in my list box I click it again now I have three of them in my list box Jeremy must not be clearing out the list box very well he's pretty bad at that but it turns out at the top of this method I am in fact clearing the list box but what I've actually done is I've used multi casting without even pointing to it now you'll notice that in this assign action where I assigned to this process people variable that we have I used a plus equals instead of an equals now anyone who is hooked up an event handler will recognize that because usually if we hook up a button click event handler in code we say plus equals and we give it our own method that's so that we can add our own method to the event to the event handler so it will get fired when the event is fired we can do the same thing with any delegate variable so what's happening is each time I click the button it's calling a sign action and it's adding a new method to it each time so the first time I click the button it adds it and then executes it the second time I click the button it adds another one and so then runs both of those the third time I click the button now there's three of them in there so that's what's happening here I had so much trouble getting my head around the head it's like wow that's kind of interesting now there is an easy way around this because inside our assign action we can just reset our variables so we can say process people equals null and so that will clear it out every time we click the button so now if we do the same thing we'll only get at one time that deserves a little bit of applause if you have to ask for it it's not genuine okay I'm going to take pity on you because I saw some people that didn't really love delegates or I'm sorry love lambda expressions so I'm going to show you how awesome lambda expressions are by modifying our assigned delegates that we have here now if you remember this this is based on the radio buttons and right now we're calling the separate methods in this separate class but what I would rather do is have code that's like really obvious and easy to read and for that I'm going to use a lambda expression now the problem with lambda expressions is this right the problem is if you don't understand them you look at it you're kind of like I have a general idea of what's that what that's doing but I don't know really what it's doing well the land' expression here is simply acting as an anonymous method and if our anonymous method matches the signature of our delegate we can assign it to that now all I have to do to kind of get to a lambda expression is to create an anonymous delegate instead of a name to delegate this terminology is really awesome I love this so what we have right now inside of our assigned delegate method this formatters default format is that last name two upper these are all named delegates they're delegates with names now the terminology does get confusing because they are also just methods but it's the delegate again represents a type that represents the method signature and then we have variables of that type and then we assign methods to that type and it makes my head hurt whenever I have to think about that terminology and I've had discussions with people of like what's the best way to talk about this stuff and usually they're like I have no idea so what I'm going to do is instead of using these name delegates I'm going to use an anonymous delegate so if you notice here I have my default method from my Matters class I'm going to highlight the parameters and the method body and I'm going to copy that code and come back over here and instead of using this for matters default directly I'm going to type in the delegate keyword and then paste and what I've just done is in lying to that code and this is what's known as an anonymous delegate which is a delegate without a name and so I have this anonymous delegate here and I kind of said that lambda expressions can be used as anonymous delegates din and I so that means I can turn this into a lambda expression now if you've never seen an anonymous delegate turned into a lambda expression you are going to be amazed if there's one thing you write down this is the thing you write down okay so are you ready I'm going to take the delegate keyword and delete it and then in between the parameters and the method body I'm going to add the equals greater than sign maybe I'm going to try to add the equals greater than sign that's our lambda operator that's it now that's a lambda expression but the thing is this isn't usually the way we see lambda expressions this is way too readable right I can see the parameter is of type person and it's called inputs that looks very obviously like a parameter and I've got my method body in curly braces well the thing about lambda spreche ins is they were designed to be very compact we got land expressions at the same time we got link and that's when we're like okay we want these really short Station's statements that we can put as parameters and methods and just have them all in one spot easy to read without like blowing up the code so there's a lot of syntactic sugar around lambda expressions that allow us to shrink this down the first one is something called parameter type inference you should remember that because if you say it while your boss is around you sound really smart all parameter type inference means is that if the compiler can figure out the type of this parameter I don't have to type it in so I can come up here to this person type that I have listed and delete it now this is still strongly-typed if I put my cursor over input it still tells me this is a person how does it know that well because I'm assigning it to our format person variable and that's a func a person string so the only thing I'm allowed to assign to this is something that takes one parameter of type person so the compiler already knows what I'm allowed to assign to this so I don't have to type in the type another thing is that if I only have one parameter I don't need parentheses around it another thing by convention is that because we're trying to make things compact it's very common to use single characters for parameter names in my lab expressions so instead of using input I might use P now when I'm picking single characters I try to pick one that reminds me of what it is since this is a person object I'm going to use P and that's to help my brain another thing is if I only have a single a single expression that has a return type I can add that has a that's returning a value I can get rid of the curly braces and the return word and that is a complete land expression and it has the same functionality as my separate method that I was calling for matters default now I know we've known each other for almost 45 minutes now but I also know you don't trust me so what I'm going to do is I'm going to comment out the four matters that default method so that it's no longer available and I'm going to run the code and we're going to see that still works yeah that's pretty cool okay let me do that one more time a little bit faster with this last name to upper so again I'm going to copy the parameters in the method body we're going to come over here and type in the delegate keyword and paste and again now I'm going to delete the delegate keyword and put in the equals greater than sign I can delete the parameter type since I've only got one parameter I can get rid of these parentheses around it by convention single character parameter names and I can get rid of the curly braces and the return keyword that doesn't seem quite as difficult as it did before does it in fact once you get used to this now you can just start typing land expressions directly into this so this first name to lowercase well I can say P goes to P dot first name dot to lower and down here for full name I can say P goes to in this case I'm going to do some string interpolation P dot last name comma P dot first name just like that and again because I know you don't believe me I'm going to comment out the entire formatters class we commented out gone so the only code that I have is the code that I'm seeing right here and my code behaves exactly the same way as it did before so again there's my default two string last name to uppercase first name to lowercase full name and when I look at this code everything I need to know about it is on this one screen and I like that I don't like to have to go to other places to look for code now obviously it makes sense to separate things when you've got big chunks you're trying to make things understandable and readable but as far as the number of lines of code that I have here on this screen I have exactly the same number of lines that I had when I was using the for matters class but now I see exactly what's going on right here next my code and I really love that so I can see oh using the default two string oh it does last name to uppercase first name to lowercase those were probably obvious based on the names of the methods but for full name what is full name game well here I can see it means last name comma space first name so I like having that code directly in front of me and once you see that again you kind of get used to it you work with it for a while and pretty soon something like this doesn't look quite so for it now I do have some other I want to hook up the checkboxes here so I'm going to go to my snippets I'm going to not going to make you watch me type all of this code because this is a lot of code but we can walk through what it's doing now since we have let me get rid of my Boop let me get rid of my taskbar so that will give me a little bit more space here lock the taskbar automatically hide there we go I think I can see the whole thing oh that's close enough so now I've hooked up things to the check boxes so I have the four check boxes now you'll notice here I don't have you know if statements that return instead what I'm doing is I'm using that plus equals operator for each of these so I can assign more than one method to the same delegate variable and then when we invoke it all of them are going to run just like we saw three copies of the same method running we can have copies of different methods that alright at the same time now this first one again we've already seen that takes the average rating and then outputs it to the list box that we have on the left hand side of the screen or right-hand side of the screen I should say now the second one is getting the earliest start date so it's using a min a cool link function on the start date to string based on short date format I will apologize for that format before you see it and I'm adding that to the output list now this third one is actually doing a message box dot show so this is where we want to show the name of the highest Raider the highest rated commander that we have on the list so it's going to do a little bit of linked order by descending based on the rating so the highest one will be at the top take the first one to string that stick it into a message box and this last one is actually going to write to the output window of our application so it's just going to do a console dot write and it's going to take the first character of the last name and then just kind of append those together so that we'll see all seven of those okay let's see how these work because multi casting man I love this stuff okay I'm going to do them one at a time because I'm not feeling really brave at the moment so there's our average rating 6.4 okay so we have some formatting for the decimal places earliest start date is 10 17 1975 now I apologize because I am American if you haven't figured that out yet and so we do our dates backwards so that's actually October 17th but we can see that in the output window and if we were to look at the items in our list looks like John Koenig was from 1975 and so that's his date up there and then for the best commander again we'll get a pop-up box which in this case says Dave Lister and we can see Dave here has a rating of 9 out of 10 stars and then we have the first letters of the last names now I want you to look way down here in this part of the screen because when I choose that one loop the output to there now these are kind of arbitrary actions I'm performing at the moment but I just want to show you know K HCl SMG that represents the last names Koenig hunt Crichton blister shared in Montana Jambu okay so I'm outputting all that now things get interesting when we start doing this together I'm just going to restart it so the output submit my console output clears because let's see what happens when I start clicking multiple ones but I'm feeling really brave I'm going to click all of them so I'm going to have all four of those methods run at the same time sort of it's really easy to think that oh I can assign like multiple methods to this delegate and when I invoke it they're all going to run and it's probably doing some magic threading on the background so everything runs at the same time no it does not do that it actually runs the methods in the sequence that they're assigned so the way that I can tell by looking at this code is if you notice I did get my average rating I got my earliest start date and then I got my message box show which is a modal dialog which means my application stops processing so if I were to look way down here in the corner where I expect to find the first letters of the last names I don't see those yet and if I click OK we'll see those pop up OOP so there's no magic threading what's happening is the methods are simply being run in the order that we assign them and things get kind of interesting in some other scenarios but before I talk about that just to show this a little more clearly this one that's using that message box I'm going to move that up in this method so it's assigned first so now if we do that same thing what we'll see is that the message box pops up but because it's model none of the other methods have run yet and this is something that's important to keep in mind because things get interesting once we start talking about what happens if you get an exception in one of these methods well the default behavior is for example if the first one gets an exception the other three will not run that's the default way that it works now there are ways around that you can handle exceptions kind of not by doing the easy dot invoke but there are ways that you can get into the method list and you can go through and loop through it and run each individually and run each individually inside a try-catch block so that if one of them fails you can still go ahead and run the other ones if you want some information on that again follow the links that are on my website for this talk and you'll see some articles that I've written about exception handling using delegates so that's something to keep in mind so again as soon as I click okay now those other three methods run now there is one other scenario we need to think about because what if none of the check boxes are checked well I get an old reference exception because if you notice I'm trying to invoke on this process people a variable that I have here that is not populated it's actually not because I didn't assign anything to it so this is something else that we need to think about is how do we handle if someone gives us a null now there's a couple ways of doing this let me just show you what Visual Studio does because the Visual Studio intellisense and the pop-up help and the little light bulb thing get so awesome with each iteration of this product so what I'm going to do is I'm going to use the one that doesn't use invoke and I'm just going to say if process people is not equal to null then go ahead and do this now you'll notice that before we look at why it's grayed out let me just show you that this actually does not throw an exception now because if nothing's checked nothing runs you know and again these still work but you'll notice Visual Studio has grayed out that if line and it's given me a little pop-up here that says hey I can make this look better okay go ahead so what it did was it went back to using the explicit invoke and then it used the cool Elvis operator so that's our null conditional operator so with the question mark before the dot if process people happens to be null it's not going to process any it's not going to run anything else so process people is no it's not good to do anything if it's not null it's going to invoke the delegate so that's cool stuff and I love how Visual Studio just says hey do you want to use this new syntax that you didn't used to have that's cool I feel really bad for the resharper guys because every time Visual Studio comes out like half of their product is in it right so they have to keep coming up with new stuff so this is really really cool stuff that I like now I could um you know I'm going to do it I'm feeling brave I'm going to code up some more because something that I'm sure you know as oh oh developers you're probably not bothered by this but I know there's some functional programmers in the room and they're really bothered with the way that I've been assigning these delegates and can I can see the look in their eyes so again I kept this code intentionally simple so that we could focus on okay how do these variables how do these delegate variables work how do we assign stuff can we do multi casting and all that but what I would probably do is instead of having actually the separate class level field I would make it so that this delegate would actually reach our this method would return the delegate itself so in this case let me go ahead and move this guy down so that he's local and we'll just set him to null to start with boo boo boo boo come on and then down at the bottom we can return actually no I don't want to do that what am i sinking I am over complicating things all I have to do is return the land expression because again these are the radio buttons so as soon as it hits one of these if conditionals that matches it should go ahead and return something appropriate now this is going to still be upset so I'm going to return null if it gets past all of those and so instead of having this oh yeah so instead of having this intermediate value I'm just going to return the delegate itself from this method so just like we can use methods as returned as parameters we can use methods as return types too and that's really cool so down here I have to get rid of this format person because this doesn't work anymore but I could actually just put a sign delegate right in here I'm not real happy with the readability for that so what I would probably do is a I call this form formatter and then I would pass this through because I don't like nesting things too deeply but that's more style than anything else but what's happening now is I'm just kind of passing this delegate this funk a person string around as a return type you know into a parameter and this and that and that rather than having you know these class level variables which we try to get rid of anyway and I would do exactly the same thing with the action so we could do the same thing we turn that type okay I'm I'm feeling like I am out of time so I'm not going to do that one it would take me two minutes and I have one minute so what we're going to do is just do a quick review of why delegates are awesome hopefully I've convinced you that it's at least something to look in a little further and hopefully you're a little more comfortable with what they are and how they work in particular funk and action are amazing you see them everywhere in Linc and quite honestly wherever I see a method that takes a funk or in action as a parameter I treat that as a big flashing sign that says put your lambda expression here so I end up using lambda expressions quite a bit and again I'm using them just as anonymous delegates it's not that hard it's really really cool and I love it it was a huge hurdle for me it took me it took me like six months before I really got lambda expressions but once I did I'm like oh that's awesome how do i how do I help other people get that - so hopefully I've done that today if you do have any questions feel free to talk to me I'll be wandering around outside and feel free to shoot me an email if you have something that comes up later because I found that if you have a question probably other people do too and so they turn into great blog articles with that thank you very much for coming [Applause]
Info
Channel: NDC Conferences
Views: 19,485
Rating: undefined out of 5
Keywords: ndc, ndc london, jeremy calrk, .net
Id: cQ5qF9PmyCQ
Channel Id: undefined
Length: 59min 27sec (3567 seconds)
Published: Sun Apr 02 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.