Do you want code that's maintainable, extensible, and easily testable? If so, then C# interfaces are here to help. In this course, we’ll take a look at how we can use interfaces effectively in our code. We'll start at the beginning ("What are interfaces?") and then explore why we want to use them. Along the way we'll create and implement own interfaces, see how to explicitly implement interfaces, and take a look at dynamic loading, unit testing, and dependency injection. All of which is made possible with interfaces.
Jeremy Clark is an application developer, technical speaker, and Microsoft MVP with over 13 years of experience in all aspects of the development lifecycle. After hours, he puts together demos and technical articles for JeremyBytes.com, a website focusing on .NET technologies.
Interfaces, Abstract Classes, and Concrete Classes This is Jeremy Clark and today we'll be talking about C# Interfaces. Our focus will be practical examples so that we'll have a good idea of what interfaces are and how they work. As developers, what do we really want from our code? Well, we want code that's Maintainable. Code that flexes under change rather than breaking. We also want code that's Extensible, code that can respond quickly to new requirements, and we want code that is Easily Testable. It turns out, interfaces can help us add these qualities to our applications. By the time we're done, you'll have a good understanding of how interfaces can be used to add Maintainability and Extensibility; you'll be comfortable implementing interfaces whether they're included in the. NET Framework or built by someone else; and you'll see how easy it is to create your own interfaces to add a layer of Abstraction to your code. As a last stop, we'll take a peek at some topics where interfaces play a key role, including Mocking and Dependency Injection. This is just a starting point. From here, there's plenty of cool technologies to explore. This course assumes that you have a basic understanding of the C# language, including things such as Classes, Inheritance, Properties, and Methods. The samples will include some more advanced features, such as XAML, WCF, and Entity Framework, but you don't need to understand these details to grasp the important concepts of interfaces.
Using Interfaces to Future-Proof Code Now that we've seen what interfaces are, it's time to start looking at "Why" we want to use them. One big area is future-proofing our code. As mentioned earlier, one of our goals is to have code that is Maintainable, code that flexes under change rather than breaking. Applications are constantly changing. We get updated business requirements or need to add new features, the trick is that when we need to make changes to one part of our application, we want to minimize the changes we need to make to the other parts of our application. There are some Best Practices that help us with this and interfaces are a big part of that. I love hearing about Best Practices, things that work for a lot of people in a lot of situations. I'll admit I wasn't always that way. Fortunately, I was surrounded by some really good developers who kept me from getting too far off course. After doing things wrong a few times, I began to think that maybe there is actually something to these Best Practices. Here's one of my favorites -- "Program to an abstraction rather than a concrete type". Now we could blindly follow this principle, but that's never the best way to do things. It's always better if we understand the reasoning behind it, then we know when to apply the principle and when we can safely ignore it. Like any craftsman, we need to understand our tools and the appropriate times to use them.
Creating Interfaces to Add Extensibility We've seen how interfaces can help us future-proof our code. Now it's time to look at how interfaces can make our code easily maintainable. Along the way, we'll explore the "How" of interfaces -- how to create our own interfaces and how we implement them. We want code that is extensible, code that can respond quickly to new requirements. If we come up with a contract that the core application can use, then we can plug in any number of different implementations that adhere to that contract. In my own work, I've created a Rules engine that allows different rule types to be easily plugged in; I've also put together work flows that allow for full control of different steps; and I've worked with an Authorization Client, which could attach to different user stores. These extensible applications were made possible with the use of interfaces. So, let's take a look at a practical example, dealing with difference sources of data.
Explicit Interface Implementation When we let Visual Studio create an Interface Implementation for us, it gives us two options -- Implement Interface and Explicitly Implement Interface. What is Explicit Implementation? To figure this out, we'll take a closer look at what it means for a class to implement an interface; we'll see the consequences of explicitly implementing an interface; and we'll dive into interface inheritance. These will help us understand why we may need to use Explicit Implementation.
Interfaces and Dynamic Loading We've created several different interface implementations. So far, whenever we've used these interfaces, we've had Compile-Time references to the Concrete Classes, but we can take things a step further. We can update our application so that it does not know anything about the Concrete Classes at Compile-Time. Instead, we dynamically load a concrete type when the application executes. This completely removes the connection between our application and any specific implementation. We've already seen how interfaces can help us make our code more Maintainable and Extensible. We'll see a little bit more on the Extensibility side when we dynamically load our implementations, but we'll spend part of our time looking at how interfaces can make our code Easily Testable, with a focus on the easy part. It's technically possible to unit test almost any type of code. If the code is not written with Testability in mind, then these tests can get very convoluted very quickly, but if we keep our tests in mind when we write our code, we can make both easily understandable application code and easily understandable unit tests. That's our goal and interfaces will help us get there. I do need to mention a very popular methodology called Test Driven Development or TDD. This keeps all of the code testable by writing the unit tests first. This is a great topic to explore further, but we won't be covering TDD today.
Advanced Topics We've taken a look at a lot of different aspects of interfaces, including how they help us add maintainability, extensibility, and easy test ability. Interfaces also play key roles in other technologies. Now that we have a good understanding of interfaces, it's time to take a look at where we can go next. We'll take a look at a few Best Practices, including the Interface Segregation Principle, which is one of the solid principles. Also, how to choose between an Abstract Class and an Interface and what should we do if we need to add or remove members from an interface. Then, we'll spend a little bit of time on some more advanced technologies, including Dependency Injection and Mocking. Interfaces play key roles in both of these.