Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
28m 27s
In C# programming, methods are essential building blocks that encapsulate reusable code and perform specific tasks. They can accept parameters, return values, and be overloaded to handle varying inputs. A more advanced concept, extension methods enable developers to add functionality to existing types, including those they don't control.
Tim Corey's video 'How To Create Extension Methods in C#' is an excellent resource. In this guide, we will explore several topics Tim covers:
In C#, a method is defined within a class. The general syntax for a method definition includes an access modifier, return type, method name, and parameters.
public class SampleClass
{
public void SampleMethod()
{
// Method implementation
}
}Public Class SampleClass
Public Sub SampleMethod()
' Method implementation
End Sub
End ClassIn Tim Corey's example at 4:05, he defines a method within a static class to create an extension method. The method defined is PrintToConsole. The definition includes all the general syntax which clearly explains how to define a method with a practical example:
public static class Extensions
{
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}
}Public Module Extensions
<System.Runtime.CompilerServices.Extension> _
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End Sub
End ModuleA 'method call' tells the program to execute a specific method defined elsewhere in the code, performing a predefined action. Methods are called using the class instance, or directly if they are static methods. For extension methods, they appear as if they are part of the type they extend. In the video at 6:18, Tim shows how to call an extension method with a primitive data type just like its predefined methods.
string demo = "This is a demo";
demo.PrintToConsole(); // Extension method callDim demo As String = "This is a demo"
demo.PrintToConsole() ' Extension method callParameters are specified in the method definition and act as placeholders for the values that are passed into the method. You can see it here after the WriteLine method is called, where message is the parameter.
public void DisplayMessage(string message)
{
Console.WriteLine(message);
}Public Sub DisplayMessage(message As String)
Console.WriteLine(message)
End SubAgain, in the extension method example that Tim Corey gave at 4:05, message is the parameter:
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}<Extension()>
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End SubArguments are the actual values passed to the method when it is called.
DisplayMessage("Hello, World!"); // "Hello, World!" is the argumentDisplayMessage("Hello, World!") ' "Hello, World!" is the argumentWhen Tim Corey calls the method at 6:20 using the dot syntax with the string type, the string value is actually being passed as a value to the PrintToConsole method:
string demo = "This is a demo";
demo.PrintToConsole(); // "This is a demo" is the argumentDim demo As String = "This is a demo"
demo.PrintToConsole() ' "This is a demo" is the argumentMethods can return values using the return statement. The return type is specified in the method signature.
public int Add(int a, int b)
{
return a + b;
}Public Function Add(a As Integer, b As Integer) As Integer
Return a + b
End FunctionWhile the extension method in Tim Corey's video doesn't return a value (void return type), you can create extension methods with return values. The return type in Tim's example is void, which means the method doesn't return any value. The following example shows how to return a value:
public static int WordCount(this string str)
{
return str.Split(' ').Length;
}<Extension()>
Public Function WordCount(ByVal str As String) As Integer
Return str.Split(" "c).Length
End FunctionMethod overloading allows multiple methods to have the same name but different parameters. This can be useful for creating flexible and intuitive APIs.
public void Display(string message)
{
Console.WriteLine(message);
}
public void Display(int number)
{
Console.WriteLine(number);
}Public Sub Display(message As String)
Console.WriteLine(message)
End Sub
Public Sub Display(number As Integer)
Console.WriteLine(number)
End SubTim Corey briefly touches on creating multiple methods for different logging scenarios at 11:24, which can be seen as an example of method overloading in a broader sense. The log method exists twice, one with one parameter and another with two parameters. The second log method at 11:39 is the overloaded version of the log method, giving it multiple functionalities under the same name.
Extension methods allow you to add new methods to existing types without having to modify or recompile them. While they're called as if they are instance methods, extension methods are defined as static.
In the previous section, 'Defining and Calling Methods', we highlighted how Tim Corey created an extension method in a separate static class and defined the static method within it to be used as an extension method. Here are some key points Tim Corey emphasizes:
this keyword, specifying the type to extend (4:58)public static class Extensions
{
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}
}Public Module Extensions
<System.Runtime.CompilerServices.Extension> _
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End Sub
End ModuleNext, Tim shows how to call an extension method on this string variable:
demo.PrintToConsole();demo.PrintToConsole()When you enter demo and start typing Print, IntelliSense suggests the PrintToConsole method. This is the new method added to the string type.
Tim explains why you can call demo.PrintToConsole():
demo is of type string.string type has been extended with the new method PrintToConsole.Although it appears that no parameters are being passed to the PrintToConsole method, Tim points out the implicit parameter passing - the demo string is passed as the first parameter to the extension method.
Tim emphasizes that extension methods have one fewer parameter in the call than in their definition. This is because the first parameter (the type being extended) is implicit.
Here, this string message means the method extends the string type, and message is the implicit parameter:
public static void PrintToConsole(this string message)<Extension()>
Public Sub PrintToConsole(ByVal message As String)Finally, when the method PrintToConsole is called, it outputs the string to the console:
Console.WriteLine(message);Console.WriteLine(message)So, calling demo.PrintToConsole() prints "This is a demo" to the console.
Tim Corey explains that extension methods can extend any type, even third-party classes that you cannot modify directly. For example, let's take a look at the SimpleLogger class at 11:09.
Here, Tim uses the hypothetical third-party class SimpleLogger that logs messages to the console (11:09). The class has two methods:
public class SimpleLogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
public void Log(string message, string messageType)
{
Console.WriteLine($"{messageType}: {message}");
}
}Public Class SimpleLogger
Public Sub Log(message As String)
Console.WriteLine(message)
End Sub
Public Sub Log(message As String, messageType As String)
Console.WriteLine($"{messageType}: {message}")
End Sub
End ClassThese methods are not ideal because the message type is a simple string, which can lead to inconsistencies. Tim suggests creating extension methods to improve the class.
Using extension methods ensures consistency in your code by always using the same message types and formatting. Here at (12:40), Tim creates a static class ExtendSimpleLogger:
public static class ExtendSimpleLogger
{
public static void LogError(this SimpleLogger logger, string message)
{
logger.Log(message, "Error");
}
public static void LogWarning(this SimpleLogger logger, string message)
{
logger.Log(message, "Warning");
}
}Public Module ExtendSimpleLogger
<System.Runtime.CompilerServices.Extension>
Public Sub LogError(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Error")
End Sub
<System.Runtime.CompilerServices.Extension>
Public Sub LogWarning(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Warning")
End Sub
End ModuleWith it in hand, (14:02) he is now able to call the extension methods on a SimpleLogger instance:
SimpleLogger logger = new SimpleLogger();
logger.LogError("This is an error");
logger.LogWarning("This is a warning");Dim logger As New SimpleLogger()
logger.LogError("This is an error")
logger.LogWarning("This is a warning")This ensures that the message types are always 'Error' and 'Warning'.
Tim adds functionality to set the console text color for error messages, ensuring they stand out:
public static void LogError(this SimpleLogger logger, string message)
{
var defaultColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
logger.Log(message, "Error");
Console.ForegroundColor = defaultColor;
}<Extension()>
Public Sub LogError(ByVal logger As SimpleLogger, ByVal message As String)
Dim defaultColor = Console.ForegroundColor
Console.ForegroundColor = ConsoleColor.Red
logger.Log(message, "Error")
Console.ForegroundColor = defaultColor
End SubTim compares this approach to directly calling the original Log methods, which could lead to inconsistencies:
logger.Log("Test error", "Error");
logger.Log("Another error", "ERROR");logger.Log("Test error", "Error")
logger.Log("Another error", "ERROR")This approach is prone to typos and inconsistent formatting.
Tim demonstrates how extension methods can be chained to make the code more readable:
public static void LogInfo(this SimpleLogger logger, string message)
{
logger.Log(message, "Info");
}
public static void SaveToDatabase(this SimpleLogger logger)
{
// Simulate saving to a database
}Public Sub LogInfo(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Info")
End Sub
Public Sub SaveToDatabase(ByVal logger As SimpleLogger)
' Simulate saving to a database
End SubNow, you can chain these methods:
logger.LogInfo("Information").SaveToDatabase();logger.LogInfo("Information").SaveToDatabase()This makes the code more readable and intuitive compared to nested method calls:
SaveToDatabase(LogInfo(logger, "Information"));SaveToDatabase(LogInfo(logger, "Information"))By using dot notation and chaining, the intent of the code is clearer and less nested.
At 20:13, Tim Corey explains that extension methods are ideal for adding functionality to classes you don't own, such as third-party libraries. This allows for enhancements without modifying the original code.
Corey also highlights using extension methods to introduce dependencies without coupling them directly to a class. For example, adding database saving functionality to a Person class without embedding database logic.
Extension methods can also apply to interfaces, as explained from 21:30, enabling multiple classes that implement the interface to share the same functionality. This promotes code reuse and simplification.
At 23:03, Tim Corey advises against overusing extension methods, especially with primitive or Microsoft-provided types, to prevent clutter and complexity. Use them sparingly and only when they offer clear benefits.
In the section between 24:54-25:40, Tim emphasizes adhering to the open/closed principle by using extension methods to add new functionality without modifying existing, stable code, thus reducing the risk of introducing bugs.
Organize extension methods by grouping them logically and placing them in separate namespaces to avoid naming conflicts and facilitate easier maintenance and debugging.
And there you have it - you now understand the basics of defining and calling methods, handling parameters and return values, and leveraging method overloading. With that, you can build robust and flexible applications in C#.
Extension methods, as explained by Tim Corey, offer a powerful way to enhance existing types and make your code more readable and maintainable. For more detailed insights and practical examples, you can watch Tim Corey's full video on How To Create Extension Methods in C#.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy