Click here to Skip to main content
Click here to Skip to main content

Understanding Extension Methods and Mixin

, 19 Jul 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
C# extension methods and Mixin implementation.

Introduction

Extension methods is a powerful concept. We will explore the nuances of extension methods in this article. This article will also look at the Mixin implementation in C#.

Background

An extension method is a static method defined in a non-generic static class, and can be invoked using an instance method syntax. Let’s look at the sample code. Shown here is a very common scenario – evaluate an expression if value is greater than 0.

int NumOne = 10;
if (NumOne > 0)
  Console.WriteLine("Number : {0} is greater than 0", NumOne);

Now, this evaluation can be abstracted out to a static method, as follows:

static bool StaticIsGreaterThanZero(int Number)
{
    return Number > 0 ? true : false;
}

And, we can revise our if condition as:

if (StaticIsGreaterThanZero(NumOne))
{
    Console.WriteLine("Number : {0} is greater than 0", NumOne);
}

By doing this, we don’t have to write an if condition all over our code. Anywhere in the program where we need a logic like if(Number > 0), we can use the StaticIsGreaterThanZero method. In fact, we can promote this method in a separate static class, and use it all over the application. Methods like StaticIsGreaterThanZero are known as helper methods. They add value by centralizing common logic and reducing code duplication / repetition. We all have seen code like this in many applications. Here is the twist – what if we want to make this static method part of the C# integer type? We want to use this static method as an instance method. Let's first code, and then we will evaluate the sample.

Step 1

public static class ExtensionMethods
{
    public static bool IsGreaterThanZero(this int Number)
    {
        return Number > 0 ? true : false;
    }
}

Step 2

if (NumOne.IsGreaterThanZero())
{
    Console.WriteLine("Number : {0} is greater than 0", NumOne);
}

In step 1, we defined a public static class ExtensionMethods and a static method IsGreaterThanZero. Notice, the IsGreaterThanZero method is very much like the StaticIsGreaterThanZero method in terms of code, functionality, and structure. The only difference is the this keyword in the method signature. Extension methods can be created by adding the this keyword in front of the first parameter. IsGreaterThanZero is an extension method. It extends the native int type. That’s why we can write code like NumOne.IsGreaterThanZero(). Extension methods can be used as instance methods. Extension methods will show up in Visual Studio Intellisense, as shown in Figure 1.

Extension Methodin visual studio IDE

Figure 1:

What if you want to extend custom types? It is possible to extend existing custom types without changing any code in the underlying type definitions. Here is a sample City type:

public class City
{
    private string _name;
    private string _state;

    public City(string name, string state)
    {
        this._name = name;
        this._state = state;
    }

    public string Name
    {
        get
        {
            return _name;
        }
    }


    public string State
    {
        get
        {
            return _state;
        }
    }
}

We want to extend the City type and add a method to evaluate the city state. This method should return true if the city is in California.

public static bool IsCityinCalifornia(City c)
{
    return c.State == "CA" ? true : false;
}

We can add this method in the class, make it a public method, and it will be available as an instance method. Alternatively, we can write IsCityinCalifornia as an extension method without changing the City class.

public static class ExtendCity
{  
    public static bool IsCityinCalifornia(this City c)
    {
        return c.State == "CA" ? true : false;
    }
}

The IsCityinCalifornia extension method can be used in our evaluation logic as:

City c = new City("Santa Ana", "CA");
City c1 = new City("Bloomington", "IN");

List<city> cities = new List<city>();

cities.Add(c);
cities.Add(c1);

foreach (City _city in cities)
{
    //IsCityinCalifornia() is an extension method
    if (_city.IsCityinCalifornia())
    {
        Console.WriteLine("City Name : {0} and City State : {1}", 
                          _city.Name, _city.State);
    }
}

Extension methods should be defined in a non-generic, static class. Otherwise, we will get a compile time error. That’s the reason for using a public static class ExtendCity. If an extension method is defined in a different namespace, that namespace can be imported through using the namespace syntax [for example, using ABC.ExtensionMethod;]. What will happen if we add the IsCityinCalifornia method as an instance method in the City type definition in addition to the extension method? As per the documentation, the instance method takes precedence over an extension method. So, the IsCityinCalifornia instance method will be used.

Mixin: Extend the type by extending the interface. A good explanation on mixin in C# can be found on this blog post. Extension methods can be used to implement mixin in C#. Let's look at the code sample.

MixinUML.GIF

interface IPerson
{
    int age { get; set; }
    String name { get; set; }
}

class Person : IPerson
{
    private int _age;
    private string _name;

    #region IPerson Members

    public int age
    {
        get
        {
            return _age;
        }
        set
        {
            if (value > 0)
            {
                _age = value;
            }
           
        }
    }

    public string name
    {
        get
        {
            return _name;
        }
        set
        {
            if (!string.IsNullOrEmpty(value))
            {
                _name = value;
            }
            else
            {
                _name = "Unknown";
            }
        }
    }

    #endregion
}

static class ExtendIPerson
{
    public static bool CanDrive(this IPerson testPerson, bool isDriver)
    {
       return isDriver;
    }
}

static void Main(string[] args)
{
    IPerson ip = new Person();
    
    ip.name = "ABC";
    ip.age = 21;

    if(ip.CanDrive(true))
    {
        Console.WriteLine(ip.name +" can drive");
    }
}

The Person type is extended by extending the IPerson interface. An extension method CanDrive is implemented in the ExtendIPerson static class. This is mixin in C#. Let's summarize the strengths and weaknesses of an extension method. First, weaknesses:

  1. Extension methods will be available as instance methods to all the instances of the type in a given assembly. For example, if you extend the native integer type, every variable of int type will be able to access the extension method as an instance method.
  2. Extension methods defined locally in any particular application may cause the type to get out of sync with its original definition. Let's say, if we have a database type dbconnection in our application framework and this application framework is used in multiple applications. We extend the dbconnection in only one application using an extension method. As a result, dbconnection in one application will have more methods as compared to its original definition. This might be confusing for many end users.
  3. Extension methods are less discoverable as compared to instance methods. For example, Person is a base class for the Teacher class. Add a CanDrive instance method in the Person class and add an extension method CanDrive on the Teacher class. An extension method on the Teacher class will never be used. The CanDrive instance method on the Person class is preferred by the compiler.
  4. Overuse of extension methods might result in code duplication and maintenance nightmare.

On the positive front, extension methods are the only way to extend third party assemblies / APIs.

  1. Let's say we have a third party SLL and want to extend a particular type in it. But we don’t have access to the code. Tools like Reflector or Object Browser can be used to probe the DLL internals. Extension methods can be used in this scenario to extend the type in that DLL.
  2. Extension methods are central to LINQ implementation. Standard query operators in System.Linq are implemented as static extension methods.
  3. Extension methods are very useful in extending sealed classes.
  4. Mixin in C# can be implemented using an extension method.

As the documentation says, use extension methods “sparingly”. Extension methods can be used in certain cases where no other solution / trick will work. There are many good examples of extension methods in the .NET framework.

Points of Interest

Good articles on Extension methods and Mixin:

  1. Using_Extension_Methods.
  2. UnderstandingLINQ.
  3. C__3_Mixin.
  4. Mixin.

History

Original article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

abhigad
Architect Wells Fargo
United States United States
MS Computer Science + Information Science
Architect at Wells Fargo [Wells Fargo Dealer Services -WFDS]
Blog: Profile

abhijit gadkari
abhijit dot gadkari at gmail dot com
Irvine-92618,CA

Comments and Discussions

 
GeneralA very effective use of extension methods - "IsNull Extension Method" [modified] Pinmemberabhigad23-Dec-08 15:57 
GeneralNit picking PinmemberPIEBALDconsult19-Jul-08 18:21 
GeneralRe: Nit picking Pinmemberabhigad19-Jul-08 19:18 
GeneralRe: Nit picking PinmemberPIEBALDconsult20-Jul-08 4:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141029.1 | Last Updated 19 Jul 2008
Article Copyright 2008 by abhigad
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid