Introduction13:05 with Jeremy McLain
In this video we'll compare and contrast subclassing, helper methods, utility methods, and extension methods.
Welcome to this workshop about C# extension methods. 0:04 I'm Jeremy. 0:08 Have you ever been coding along and 0:10 thought, I wish this class I'm using had methods for doing X, Y, or Z? 0:11 For example, just the other day, I wanted to randomly pick an item from a list. 0:15 But neither the Random class nor the List class have methods for doing this. 0:21 Both the list and the Random class are provided by the .NET Framework. 0:25 So I can't just go and open up their code files and add a method to them. 0:29 Fortunately, .NET has provided a way to add methods to any class, 0:34 even if we don't have access to the source code. 0:38 This is the purpose of C# extension methods. 0:41 Let's take a look at the code that I wrote to randomly pick an item from a list. 0:44 Here we have a list of the synonyms for best, and 0:48 down here I print out, my dog Jojo is the synonym for best dog. 0:52 To get the synonym for 0:58 best, I call this GetRandomItem method and pass it that list. 0:59 I wrote this GetRandomItem method to get a random item from the list. 1:03 Here it takes the list and I construct a random object and 1:08 I call next on that random object, and what this does is it just gets 1:13 a random index from the list and then returns the item at that index. 1:17 Now on the surface, this looks pretty good, but 1:22 there are a few things we could do to improve it. 1:25 For one this GetRandomItem method isn't very reusable. 1:27 It's stuck in the program class. 1:31 It's likely that there are other places in the code where we 1:33 might want to get a random item from a list. 1:36 Methods like this are often called helper methods because 1:39 they're used to help the class do something minor. 1:42 They aren't considered a core part of the class, and 1:45 helper methods like these can quickly clutter up a class. 1:48 So it's better if we could move this method outside of this class so 1:51 that it could be reused by other code. 1:55 Also, it would be more readable if we could just 1:57 say, SynonymsForBest.RandomItem, 2:00 like this. 2:09 But the List class doesn't have a method named RandomItem. 2:11 This is what C# extension methods can be used for. 2:16 We can add methods so that they appear as if they're part of the original class. 2:19 Not every language has extension methods, though, and 2:24 developers have been coding for a long time without them. 2:27 So, let's take a look at how we would solve this problem 2:30 without using an extension method first. 2:33 One way we could do this is to extend the list class directly using inheritance. 2:35 So, let's create a class library. 2:41 Just right click on the solution, go to Add > New Project, 2:45 select Class Library, and here I'll create 2:51 a new class library called Treehouse.Common. 2:56 I often create a class library to contain some of the common code that I want to 3:01 share between different programs. 3:06 That's where we want to put our List class. 3:09 Let's delete this file and 3:11 then add a new class for our list. 3:17 I'm just gonna to call it List, but I'll put it in a different namespace so 3:25 that it doesn't conflict with the System.Collections.Generic.List. 3:30 So I'll say, Treehouse.Collections.Generic. 3:35 The List will need to be public so 3:44 that it can be accessed from outside of the class library. 3:47 And it will be a subclass of the System.Collections.Generic.List. 3:52 We need to specify what type of item we want our list to contain. 4:04 So add a type parameter here. 4:10 Now if we were doing this properly, we would create constructors for 4:13 each of the constructors in the base System.Collections.Generic.List class. 4:17 Let's skip that for right now. 4:22 Right now, let's copy this GetRandomItem method from 4:24 the program class over here and move it over here to the List class. 4:29 Let's make it public. 4:39 And it's no longer static. 4:42 We'll just call it RandomItem. 4:46 And instead of returning a string, 4:48 we'll have it return the type of the item that's contained in the list. 4:49 We don't need to pass it the list and 4:54 we'll get the item from the list itself, 4:58 just say this, and just change this to Count. 5:04 So now we have an instance method on our new List class that will 5:09 return a random item from the list. 5:14 Something else we could do here so that we're not creating a new random object 5:17 every time the random method is called, or the random item method is called, 5:21 is we can move this outside of this method and 5:26 make it a static field, so just say private static. 5:30 Random equals new random, type random. 5:38 There we go. 5:48 Now if we go back over to the program class, 5:51 we still don't have the random item method on our list. 5:54 That's because we're still using the System.Collections.Generics 5:57 version of the list. 6:01 We need to change it to use our new List. 6:03 So we'll just change this namespace up here from 6:06 System.Collections.Generic to Treehouse.Collections.Generic. 6:10 Looks like I probably misspelled. 6:20 I see what the problem is. 6:23 We need to add a reference to our new class library here. 6:24 So say Add Reference > Projects > Treehouse.Common. 6:28 There we go, that should fix it. 6:35 So now we're using our new type of list, 6:41 which is just a subclass of the list provided by .NET. 6:44 However, in order to use this new method, 6:48 the list had to be of type Treehouse.Collections.Generic.List, 6:51 instead of .NET's implementation of the list. 6:56 We're no longer using the List class from .NET, but had we gotten this list of 6:59 synonyms from some other source or library of code that didn't know about 7:03 our new fangled list type, it probably wouldn't be the right type. 7:08 Most likely, it would be the List that comes with .NET. 7:13 Sometimes it makes sense to make a subclass of List and 7:16 create our own list that has a bunch more features in it. 7:21 But adding one method isn't enough justification 7:24 to warrant creating a whole new type of List. 7:28 Instead of creating a new type of List, 7:31 we could just create what many refer to as a utility method. 7:34 To do that, let's change our List class over here. 7:38 Let's actually change it to be called ListUtils. 7:42 This is a common way of naming classes that contain utility methods. 7:48 We'll also make it a static class. 7:53 Let's change our RandomItem method so 8:04 that it takes a Type parameter, and we'll also make it static as well. 8:07 In order for 8:15 it to get an item from the list, it needs to take the list as a parameter. 8:16 So we'll say List<T>, 8:20 and we just call it list. 8:24 So this is starting to look like the method that we originally had 8:29 in the program class. 8:33 We also need to add the System.Collections.Generic 8:40 namespace up here. 8:47 Now over in Program.cs, 8:51 we'll need to change this back to 8:55 System.Collections.Generic as well. 9:00 But now we don't have a List class that contains a RandomItem method. 9:08 So instead, 9:12 what we have to do is call the RandomItem method that's in our ListUtils class. 9:13 So it'll be ListUtils.RandomItem, and 9:19 we'll pass in the synonymsForBest list. 9:23 We still need to have a using statement for 9:34 our Treehouse.Collections namespace. 9:39 There we go. 9:47 While we're at it, let's go ahead in change the name of this file to be 9:48 ListDetails as well, to match the class name. 9:53 So now we have our reusable RandomItem method. 10:01 But it isn't quite as readable or useful as the RandomItem 10:05 method that we had when we could just call it right on the List class. 10:10 We can get some of this readability back and 10:14 ease-of-use by using a C# extension method. 10:16 What we want is to be able to call the RandomItem 10:19 method right on the list, like this. 10:27 To do that, let's take another look at our ListUtils class. 10:33 To turn our RandomItem method into an extension method, 10:37 all we have to do is add the keyword this here. 10:42 Now our red squiggly lines have gone away and 10:48 we can call the RandomItem method directly on a list. 10:51 So adding the List keyword here right before the type parameter 10:55 made this static method into an extension method. 10:59 What the List parameter does is it tells C# that 11:03 this method can be called on any object of type List. 11:07 In order for this to be an extension method, 11:15 it must be a public static method inside of a public static class. 11:17 So this works just like a utility method, only we don't have to say 11:23 ListUtils.RandomItem and then pass in the list. 11:28 Instead, we can just call RandomItem right on an object of List. 11:32 In fact, we can even make it better than that. 11:37 We can change the type that the extension method can be called on to an interface. 11:40 So now, the RandomItem method 11:47 can be called on any object that implements the IList interface. 11:49 That's pretty cool. 11:54 To make it clear that this class contains extension methods, 11:56 let's rename the name of the class. 12:00 Let's name this IListExtensions. 12:03 We'll also rename the file. 12:10 Let's go back to Program.cs. 12:20 Notice what happens when I comment out this using statement for 12:25 Treehouse.Collections.Generic. 12:30 We lose the ability to call the RandomItem extension method on synonymsForBest. 12:33 This is how we provide scope for extension methods. 12:39 By saying that we're using the Treehouse.Collections.Generic namespace, 12:43 we're also saying that we want to have access to 12:47 any extension methods that are declared inside that namespace. 12:50 So extension methods are pretty nifty and 12:54 they help to keep our code clean, dry, and readable. 12:57 Let's take a look at a few more features of extension methods 13:00 by writing a few more. 13:04
You need to sign up for Treehouse in order to download course files.Sign up