5,699,997 members and growing! (17,413 online)
Email Password   helpLost your password?
Languages » C# » Generics     Intermediate License: The Code Project Open License (CPOL)

Using Generic Extension Methods

By Samer Abu Rabie

Using Generic Extension Methods
C# (C# 3.0, C#), Architect, Dev, Design

Posted: 4 Sep 2008
Updated: 24 Oct 2008
Views: 2,450
Bookmarked: 9 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
12 votes for this Article.
Popularity: 2.49 Rating: 2.30 out of 5
6 votes, 50.0%
1
1 vote, 8.3%
2
1 vote, 8.3%
3
1 vote, 8.3%
4
3 votes, 25.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

In this article I will get a close eye on the concepts of Generics (introduced in C# 2.0) and Extension Methods (Introduced in C# 3.0), and how to mix both concepts together to get a new concept of Generic Extension Methods that will make a difference in our class Desgins.

Background

This article is talking about two concepts merged together: Generics and Extension Methods, so in order to understand it you got to be familiar with both concepts, so I am going to summarize on each one.

Generics are a new feature in C# 2.0 and the common language runtime which introduces the concept of type parameters, so you can just specify your type for a class or a method at runtime.

Extension methods are a new feature in C# 3.0 and the common language runtime in which allows existing classes to use extra methods (extension methods) without being implemented in the same class or got by inheritence.

Generics Sample

Below is a sample of using generics with methods, the same concept apply to classes, but for the purposes of this article we are gonna use a generic method:

public class SomeClass

{

///Using of one type as parameter
public string Method1<TInput>(TInput obj1)

{
    //return a serialized object as string for example
}

///Using of two types as parameters
public TReturn Method2<TReturn, TInput>(TInput obj1)

{
    //map data from an instance of TInput type to TReturn type and return an
    //instance of TReturn type
}

///Using of three types as parameters
public TReturn Method3<TReturn, TInput1, TInput2>(TInput1 obj1, TInput2 obj2)

{
    //Map data from an instance of TInput1 and TInput2 types to an
    //instance of TReturn type and return that instance
}
}

Fairly Simple, for a certian method you declare types before the () and use them as your input or output or both or even inside the method body without being used as Input or Output.

Extension Methods Sample

Below is a sample of using extension methods

public class MyClass{

private string m_Name;
public string Name{
get{return m_Name;}
set{m_Name=value;}
} 
}
 
public ExtensionMethodsClass{
public static string DoSerialize(this MyClass entity){
//Serialze the entity object and return its string represenatation
}
}

Note the use of this keyword in the DoSerialize method, this indicate that an instance of MyClass will only be able to call this method like this:

MyClass instance=new MyClass();
instance.DoSerialize(); 

Although that the DoSerialize method is not a member of MyClass, you can just call it as its a member of it !

The input parameter of the DoSerialize Method the this keyword is telling us that an instance of type MyClass will call DoSerialize as its a member in it.

Pretty ... ha ! ... now lets take a look on how to merge the two concepts together, its fabulous actually ;)

Generic Extension Method

As we have seen earlier, the this keyword will determine which type will call the extension method as its a member, now lets replace the type of this keyword (MyClass) with the Generic Type T as follows:

public ExtensionMethodsClass{
public static string DoSerialize<T>(this T entity){
//Serialze the entity object and return its string represenatation
}
}

Up to here, any type will use this extension method to make a serialization using the DoSerialize method which is good and bad in the same time ! Good because we are generic in our types and alot of types will use this method and no need to implement the same extension method over and over again, but bad because it will receive any type ! what if we passed a non-serializable type !?? Oops ... I think this will make a problem for us that we should take care of !

Using the 'Where' Clause with Generics

Here comes the role of the Where clause, the where clause is used to determine the type used as generic, more likely the specifications of the type we are going to use as generic, we can determine if it should have a default constructor too, or the interfaces it should be implementing, and focus on that, because its the key to a good implementation as we would see at the end of this article. No further explanation, lets take a look at the code sample below:

public ExtensionMethodsClass{
public static string DoSerialize<T>(this T entity) where T: MyClass{
//Serialze the entity object and return its string represenatation
}
}

Using the above code we determined that the generic type used should be of type MyClass or inherited from MyClass, seems good, but actually its not so far ! because by determining the type to be MyClass we are not much different from our first implementation using :

public static string DoSerialize(this MyClass entity){ ...}

which we wanted to expand from the whole begining ! so how can we get it all together ?!

When and How to Use it ? and the effect on Design

Usually we have an application, we have alot of business classes in it, most probably we have that base class or interface for all these business classes, and common behaviours are replaced within that class or interface, now these behaviours should be only implemented for our business entities, and not any other .net classes for example, so we have two options:

  1. Place these behaviours in the base class or interface and all entities will inherit it.(Usually done)
  2. Make a generic extension method where the type is the base class or interface. (New way of doing it)

Both solutions will do the trick for you, but it will affect your design on the long run, you see, inheritence had always tied our code with its limitations, its not that this is a bad thing, its just the way inheritence work, and sometimes solving problems using inheritence will lead to major problems in the design then to maintenance problems in happey cases, so you got to be carefull doing so, in the other hand, Generic Extension Methods will make us avoid those limitations by Inheritence because its expandable, lets take a look at the following code which will illustrate a good example of Generic Extension Methods and helping in the design as well:

public class BaseClass{
}
public class MyClass: BaseClass, ISerializable{
}
public class YourClass: BaseClass, ISerializable{
}
public class HisClass: ISerializable{
}
public class HerClass: ISerializable{
}
public ExtensionMethodsClass{
public static string DoSerialize<T>(this T entity) where T: BaseClass{
//Serialze the entity object and return its string represenatation
}
}

As we can see in the above code, we have four ordinary classes and an ExtensionMethods Class, the four classes are serializable, the classes MyClass and YourClass will have the ability to use the Extension Method DoSerialize, because they inherit from the BaseClass class, on the contrary the classes HisClass and HerClass will not have that option.

But in this context, a member here in code project notated how using:

public static string DoSerialize<T>(this T entity) where T: BaseClass { ...}

will be different from using :

public static string DoSerialize(this BaseClass entity){ ...}

Actually in this context it wont be much of a difference... but lets take a look to the flexibility we could have by using the following example:

//Our Interfaces
public interface IFirstInterface
    {
    }
public interface ISecondInterface
    {
    }


//Our Classes
public class AClass : IFirstInterface
    {
    }
public class BClass : ISecondInterface
    {        
    }
public class CClass: IFirstInterface , ISecondInterface
    {
    }


//Our Extension Methods Class
public static class ExtensionMethodsClass
    {
public static void DoSerialize<T>(this T entity) 
where T: IFirstInterface, ISecondInterface
        {
        }
    }

I think the code is obevious enough to explain it self :) ... simply an instance of CClass will only be able to call the extension method DoSerialize() and neither of AClass nor BClass:

AClass A=new AClass();
BClass B=new BClass();
CClass C=new CClass();
A.DoSerialize();//Compiler Error
B.DoSerialize();//Compiler Error
C.DoSerialize();//Works Fine

Conclusion

Generics and extension methods are two great concepts in which they really help in our design of classes, they help us in minimizing our code and use the concept of Code Refactoring, in the addetion maintenance will be always much easier using extension methods, but I think we should always keep an eye on the fact that our design demands will control what technologies we should use, not the other way around, but understanding our technologies will help us more in taking our major decisions in our designs !

History

  • Created the Article September 4th, 2008
  • Updated the Article September 5th, 2008

License

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

About the Author

Samer Abu Rabie


Samer is a Computer and Digital Electronics Engineer, he lives in Jordan in a small town called Ein Albasha. Software programming has brought his attention since he saw the computer for the first time in 1994. When he joind the university he started to learn computer languages like C++ and Java, with the release of .NET he started with C# from the very begining.

Samer worked on a fair number of personal projects as part of fun, enjoyment or even for money making, mostly related to integration between hardware and software (e.g Security Systems, Sensors, Cameras, Bluetooth ... etc), which gave him a good knowledge in this area and the ability to invent various complex designs to adhere for external elements effect those systems.

Currently he is working for Estarta Solutions since March 2006, a leading software company in Jordan, mainly he is interested in the various aspects of .NET development (Web, Windows, Biztalk, Design Patterns ... etc ), through his work with his current company he managed to get powerfull knowledge in these areas and Integration in general.

If you want to contact Samer do it through his E-Mail : ce.samer@gmail.com
Occupation: Software Developer
Company: Estarta Solutions
Location: Jordan Jordan

Other popular C# articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 4 of 4 (Total in Forum: 4) (Refresh)FirstPrevNext
GeneralRate this ArticlememberSamer Abu Rabie10:13 12 Sep '08  
GeneralHuh?memberPIEBALDconsult17:49 4 Sep '08  
GeneralRe: Huh?memberSamer Abu Rabie1:24 5 Sep '08  
GeneralRe: Huh?memberPIEBALDconsult5:27 5 Sep '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Oct 2008
Editor:
Copyright 2008 by Samer Abu Rabie
Everything else Copyright © CodeProject, 1999-2008
Web20 | Advertise on the Code Project