views:

84

answers:

3

All of my classes implement an interface IPrettyPrint. With extension methods I can add a PrettyPrint method to a double e.g. (List<T>, ...) but is there any possibilty that double supports IPrettyPrint aswell? Anyone that likes to use the PrettyPrint method can rely only on IPrettyPrint.

+3  A: 

No, unless you use a library that allows "duck typing". And even then I think you'd struggle if the method was only implemented in an extension method.

Don't be fooled by extension methods - you're adding nothing to the type itself, they're only providing "syntactic sugar" which is then interpreted by the compiler.

David M
+1  A: 

Extension methods are a compiler feature, not a runtime feature--they emulate you adding a method to a Type, but if you decompile the code you'll see it doesn't actually do any such thing (.NET uses a static/closed type-system, so the only way to actually add a method to a type is to inherit from the type and add the method to your new type)

So, technically, double never supports IPrettyPrint--the compiler just pretends that it does.

STW
A: 

Duck typing can be emulated using reflection- if the type supports the operation (ie. has the method defined that you're looking for), then it implicitly is of that interface (even though you never did that), and you should call it. Otherwise, it doesn't!

The problem is, C# reflection is a bit slow, and it would be wasting your time in most circumstances. Example code follows:

public static object To(this string value, Type t) {
  object obj;

  // This is evil, I know, but is the most useful way to extend this method
  // without having an interface.
  try {
    MethodInfo method = t.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public,
      null, new Type[] { typeof(string) }, null);
    Preconditions.Check(method.ReturnType == t, "The return type doesn't match!");
    obj = method.Invoke(null, new object[]{value});
  } catch (Exception e) {
    throw new CoercionException("I can't coerce " + value + " into a " + t.Name + "!", e);
  }
  return obj;
}

For those of you who like stats, when reflection is required, the lookup of the method is close to nothing. However, the invocation of the method:

obj = method.Invoke(null, new object[]{value});

Is a performance hog and takes about 4-5ms to execute.

Tim