扩展方法&接口

时间:2010-06-29 20:15:40

标签: c# extension-methods

我的所有类都实现了一个接口IPrettyPrint。使用扩展方法,我可以将一个PrettyPrint方法添加到一个例如(List<T>,...)但是有没有可能双重支持IPrettyPrint?任何喜欢使用PrettyPrint方法的人都只能依赖IPrettyPrint。

3 个答案:

答案 0 :(得分:3)

不,除非您使用允许“鸭子打字”的库。即便如此,如果方法仅在扩展方法中实现,我认为你很难。

不要被扩展方法所迷惑 - 你没有向类型本身添加任何东西,它们只提供“语法糖”,然后由编译器解释。

答案 1 :(得分:1)

扩展方法是编译器功能,而不是运行时功能 - 它们模拟您向Type添加方法,但如果您反编译代码,您将看到它实际上没有做任何此类事情( .NET使用静态/封闭类型系统,因此实际向类型添加方法的唯一方法是从类型继承并将方法添加到 new 类型中)

因此,从技术上讲,double从不支持IPrettyPrint - 编译器只是假装它。

答案 2 :(得分:0)

可以使用反射模拟鸭子类型 - 如果类型支持操作(即,具有您正在寻找的方法),那么它隐含地是该界面(即使您从未这样做过),并且您应该叫它。否则,它没有!

问题是,C#反射有点慢,在大多数情况下浪费你的时间。示例代码如下:

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;
}

对于那些喜欢统计数据的人来说,当需要反射时,方法的查找几乎为零。但是,调用方法:

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

性能耗费并且需要大约4-5ms才能执行。