blog@mcZen

Software, life, and leisure

Generic Extension Methods

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

May 1, 2009 6:17 PM

mike

Generics 

Generics within C# give us the ability to create classes that provide functionality in a generic way.  This means we can take a class that has some underlying type and implement it so that all types can be used by the container class.  System.Collections.Generics provides some great examples of generics with their List and Dictionary implementations.

example:
System.Collections.Generics.List<string> types = new System.Collections.Generics.List<string>();
AND
System.Collections.Generics.List<Rect> types = new System.Collections.Generics.List<Rect>();

The implementation of List is standard but the template argument can be any available type.  We can also have generic functions, where the function defines a template and uses the generic type as either arguments or in the function.

Extension Methods 

Extension methods provide nice flexibility to extend existing class within .NET.  They allow us to add functions to classes that we can call on the object like it is an actual method on the class itself. 

example:
public static partial class Tools
{
   public static string ToBase64(this string s)
   {
      return System.Convert.ToBase64String( System.Text.Encoding.Unicode.GetBytes(s) );
   }
}

And we can call this function like it is part of the string class. 

string s = "base64";
string b64 = s.ToBase64();

The key parts to creating extension methods are they need to be in a static class and the first parameter has the "this" keyword which will apply the method to the given class.

Generic Extension Methods 

So now onto the topic: Generic Extension Methods.  What this means is creating an extension method from a generic function template.  So you now are probably asking "WHY?" or "When would I use this?"  Both are great questions, so I've got a great example.

I tend to be pattern oriented.  I use patterns constantly throughout my code.  One pattern is setting a property value and notifying listeners that the property has changed.  Instead of writing the same code over and over which checks the equality, then calls the handler if the value did-in-fact change.  Using a generic extension method is perfect for this use case. 

My code:
public static partial class Extensions
{
   public static bool SetAndNotify<T>(this T newValue, ref T oldValue, object sender, string propertyName, System.ComponentModel.PropertyChangedEventHandler handler)
   {
      if (newValue==null && oldValue==null) return false;
      if (newValue.Equals(oldValue)) return false;
      oldValue = newValue;
      if (handler!=null)
         handler(sender, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
      return true;
   }
}

And to use it:
...
   public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
   private SomeType _MyProperty = null;
   public SomeType MyProperty
   {
      get { return _MyProperty; }
      set { value.SetAndNotify<SomeType>(ref _MyProperty, this, "MyProperty", PropertyChanged); }
   }
...

As you can see, anytime I need to notify when a property is changed, I can just use the above code over and over.  It's important to note that with this code, I pass the reference of the member variable.  This allows me to change the value.  And there you have it, a Generic Extension Method.  

It should also be noted... This code is only checking for nulls.  we should probably also check for default(T) in the instance where T is a struct, but I don't have time to try it...

UPDATE: You can also call the SetAndNotify without explicitly declaring the template, but I like to be explicit.
[Insert explicitive here]

C# Generics and C++ Templates are not the same

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

December 1, 2007 8:32 AM

mike

I found a good example of when not to try to use generics.
I was obviously back in my C++ mindset when I tried to do this:

public class Test
{
private void Func(string s) {/*do something*/}
private void Func(int i) {/*do something*/}

public void GenericFunc<T>(T t)
{
Func(t);
}

public void main()
{
GenericFunc<string>("String");
GenericFunc<int>(1);
}
}

This (should) produces the nice compile errors:
CS1502: The best overloaded method match for 'Test.Func(string)' has some invalid arguments
CS1503: Argument '1': cannot convert from 'T' to 'string'

The reason I was trying to write this code was to reduce the amount of code I was writing. I had inconviently consolidated several functions that did the same thing into one Generic function, however, there was one specific difference for each method - the call to Func(Type) which was radically different between types. So even though I had declared the functions for which I was using, we get a compile error because .NET requires generics to be fully generic. Converting the syntax to C++ and compiling as c++ would result in a happily running piece of code.

Here is the SDK documentation for it:
Differences Between C++ Templates and C# Generics (C# Programming Guide)

Reading the last key point:
C++ allows code that might not be valid for all type parameters in the template, which is then checked for the specific type used as the type parameter. C# requires code in a class to be written in such a way that it will work with any type that satisfies the constraints. For example, in C++ it is possible to write a function that uses the arithmetic operators + and - on objects of the type parameter, which will produce an error at the time of instantiation of the template with a type that does not support these operators. C# disallows this; the only language constructs allowed are those that can be deduced from the constraints.

Powered by BlogEngine.NET 1.4.5.7