Методы расширения и интерфейсы - PullRequest
1 голос
/ 30 июня 2010

Все мои классы реализуют интерфейс IPrettyPrint. С помощью методов расширения я могу добавить метод PrettyPrint к двойному, например. (List<T>, ...) но есть ли возможность, что double также поддерживает IPrettyPrint? Любой, кто любит использовать метод PrettyPrint, может полагаться только на IPrettyPrint.

Ответы [ 3 ]

3 голосов
/ 30 июня 2010

Нет, если только вы не используете библиотеку, которая позволяет "вводить утку".И даже тогда я думаю, что вы будете бороться, если метод был реализован только в методе расширения.

Не обманывайте себя методами расширения - вы ничего не добавляете к самому типу, они только предоставляют«синтаксический сахар», который затем интерпретируется компилятором.

1 голос
/ 30 июня 2010

Методы расширения - это функция компилятора, а не функция времени выполнения - они эмулируют добавление вами метода к Type, но если вы декомпилируете код, вы увидите, что он на самом деле ничего такого не делает (.NET использует статическую / закрытую систему типов, поэтому единственный способ фактически добавить метод к типу - это наследовать от типа и добавить метод к вашему типу new )

Таким образом, технически, double никогда не поддерживает IPrettyPrint - компилятор просто делает вид, что делает.

0 голосов
/ 30 июня 2010

Утиную типизацию можно эмулировать с помощью отражения - если тип поддерживает операцию (т. Е. Имеет определенный метод, который вы ищете), то он неявно относится к этому интерфейсу (даже если вы никогда этого не делали), и выдолжен это назвать.В противном случае это не так!

Проблема в том, что отражение 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-5 мс.

...