Что касается статических методов, используемых в неуниверсальных контекстах, я согласен с тем, что не имеет большого смысла разрешать их в интерфейсах, поскольку вы не смогли бы их вызывать, если бы у вас была ссылка на интерфейс в любом случае. Однако в языковом дизайне есть фундаментальная дыра, созданная за счет использования интерфейсов НЕ в полиморфном контексте, а в общем. В этом случае интерфейс вовсе не интерфейс, а скорее ограничение. Поскольку в C # нет концепции ограничений вне интерфейса, в нем отсутствуют существенные функциональные возможности. Дело в точке:
T SumElements<T>(T initVal, T[] values)
{
foreach (var v in values)
{
initVal += v;
}
}
Здесь нет полиморфизма, универсальный использует фактический тип объекта и вызывает оператор + =, но это не удается, поскольку он не может точно сказать, что этот оператор существует. Простое решение - указать это в ограничении; простое решение невозможно, потому что операторы являются статическими, а статические методы не могут быть в интерфейсе и (вот в чем проблема) ограничения представлены как интерфейсы.
Что нужно C #, так это реальный тип ограничения, все интерфейсы также будут ограничениями, но не все ограничения будут интерфейсами, тогда вы могли бы сделать это:
constraint CHasPlusEquals
{
static CHasPlusEquals operator + (CHasPlusEquals a, CHasPlusEquals b);
}
T SumElements<T>(T initVal, T[] values) where T : CHasPlusEquals
{
foreach (var v in values)
{
initVal += v;
}
}
Уже было много разговоров о создании IArithmetic для всех числовых типов для реализации, но есть опасения по поводу эффективности, поскольку ограничение не является полиморфной конструкцией, создание ограничения CArithmetic решило бы эту проблему.
13.08.2013
public static object MethodName(this IBaseClass base)
внутри статического класса. Обратной стороной, однако, является то, что в отличие от наследования интерфейса - это не заставляет / не позволяет отдельным наследникам хорошо переопределять методологию. 03.11.2012T
для реализаций классов илиref T
для реализаций структур. Эффективность некоторых интерфейсов, таких какIEnumerable<T>
, можно значительно повысить, добавив такие элементы, какint Move(int)
, чтобы перемещать более одного элемента за раз. 01.09.2016SomeEnumerable.Count()
превращается вEnumerator.Count(SomeIEnumerable)
, если компилятор знает о последнем методе расширения. То, что я описываю, позволило бы добавить что-то вродеbool Move(ref int)
в качестве фактического членаIEnumerable<T>
, при этом среда выполнения .NET использует атрибуты, прикрепленные к этому интерфейсу, для автоматического создания реализации типаbool Move(ref int n) { return IEnumerable<T>.Move(this, ref n); };
. Классы, которые могут поддерживать быстрый переход по N (как _6 _... 13.09.2016MoveNext
соответствующее количество раз. Обратите внимание, что если кто-то использовалAppend
для соединения переданного 1 000 000 элементовList<T>
с итератором из 12 элементов, попытка пропустить 1 000 0005 элементов могла бы быть эффективно обработана путем создания перечислителяList<T>
с просьбой переместить 1 000 005 шагов, найдя выяснилось, что не хватило 5 элементов, а затем попросил итератор продвинуть 5 элементов. Намного лучше, чем звонить ... 13.09.2016List<T>.Enumerator
1000000 раз. 13.09.2016