Generic method return types

Generics don’t just have to be used at the class level. You can also use them to pass type information to methods.

My favourite example of this is having a generic return type so you can get strongly typed information from a generally useful method without having to cast the result. I first saw this when using ArtOfTest to write unit tests for webpages. Their API hads a nice feature where you can specify the type of element you’re looking for when querying the webpage’s DOM.

The type place holder is declared after the method name and then can be used in the same way you’d use a type place holder declared for a whole class:

public static T MethodName() where T : constraints
{
    // do stuff
    return (T) result;
}

Then to call the method, you pass the real type in angled brackets after the method name:

int i = MyClass.MethodName();

For a real example here’s some code to grab a strongly typed value from the web.config file:

public class Config
{
    public static T GetValue(string key, T defaultValue) where T : struct
    {
        if (ConfigurationManager.AppSettings[key] != null)
        {
            Type type = typeof(T);
            MethodInfo parse = type.GetMethod("Parse", new Type[] { typeof(string) });
            if (parse != null)
                return (T)parse.Invoke(null, new object[] { ConfigurationManager.AppSettings[key] });
        }
        return defaultValue;
    }

    public static T GetValue(string key) where T : struct
    {
        return GetValue(key, default(T));
    }
}

The code that uses it would look something like this

int myValue = Config.GetValue("intValue");
Posted on 05 May 08 by Helen Emerson (last updated on 05 May 08).
Filed under .NET

Comments

Alex 07 May 2008

Another cool thing related to generics I recently discovered is to have a generic base class. Then you can have derived classes working with different key properties. By “key” I mean the properties that really define functionality of the class.

public abstract class EditorProvider : EditorProviderBase where TEditorControl : WebControl, new()
{
public EditorProvider():base()
{
}

TEditorControl _editor;
[
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
TypeConverter(typeof(ExpandableObjectConverter)),
]
public TEditorControl EditorControl
{
get
{
if (this._editor == null)
this._editor = this.CreateEditor();
return this._editor;
}
}

protected virtual TEditorControl CreateEditor()
{
return new TEditorControl();
}
}

public class TextBoxProvider:EditorProvider
{
public TextBoxProvider()
{
}

}

Now the TextBoxProvider has its EditorControl property of type TextBox and it nicely allows editing the textbox properties at design time as well.

Alex

P.S. How are you Helen? How’s the new company treating you? :-)
We really miss you here… And not only because of the grid bugs :-D

Helen 07 May 2008

Thanks Alex! That’s a great tip! I miss you guys too, but not the grid bugs. ;)