views:

200

answers:

2

I have an extension method that I would like to overload so it can handle both reference types and nullable value types. When I try to do this, however, I get "Member with the same signature is already declared." Can C# not use the where qualifier on my generic methods to distinguish them from each other? The obvious way to make this work is to give each method a distinct name, but this doesn't seem like a very elegant solution to me. What is the best way of making this work?

Example:

public static T Coalesce<T>(this SqlDataReader reader, string property) where T : class
{
    return reader.IsDBNull(reader.GetOrdinal(property))
               ? null
               : (T) reader[property];
}

public static T? Coalesce<T>(this SqlDataReader reader, string property) where T : struct
{
    return reader.IsDBNull(reader.GetOrdinal(property))
               ? null
               : (T?)reader[property];
}

// Usage
var id = reader.Coalesce<System.Guid?>("OptionalID");
+5  A: 

This works if the SqlDataReader.Item[string] property type is object.

public static T Coalesce<T>(this SqlDataReader reader, string property)
{
    return reader.IsDBNull(reader.GetOrdinal(property))
               ? default(T)
               : (T) reader[property];
}
280Z28
Perfect! Score one for the ObviousThingsIMissed team. :)
Joseph Sturtevant
I actually deleted this post to start with thinking the cast would cause a compile problem - but realized a bit later that it's covered as long as the Item property type is object. :o
280Z28
+1  A: 

As @280Z28 pointed out, in your case you can handle both cases with one method. However, if you really wanted two methods with the same signature but different internals based on the passed-in type, that isn't possible in C#.

From Differences Between C++ Templates and C# Generics on MSDN:

  • C# does not support explicit specialization; that is, a custom implementation of a template for a specific type.
  • C# does not support partial specialization: a custom implementation for a subset of the type arguments.
bdukes