2013-06-16 2 views
3

Этот вопрос исходит из предыдущего обсуждения на C++-функторах (Do functors have an equivalent in C#?).Почему C# не допускает перегрузку оператора()?

Почему C# не допускает перегрузку оператора()?

Вы можете перегружать операторы, но какое преимущество было бы, если бы оператор() также мог быть перегружен?

+4

Очень мало. Лямбдас и делегаты делают это почти бессмысленным. –

+0

Вы размываете линию между функциями и объектами (которые уже есть делегаты) и путают корпоративных программистов-дронов, приводя к катастрофе библейских масштабов (огонь и сера, спускающиеся с неба!) Реки и моря кипят! Сорок лет тьмы! Землетрясения , вулканы! Мертвые поднимаются из могилы! Человеческая жертва! Собаки и кошки, живущие вместе! Массовая истерия!) Я думаю, мы все можем согласиться, что лучше избегать этого. –

+1

BTW, в C#, 'operator()' написано 'Invoke'. –

ответ

2

C# имеет operator(), который он называет Invoke.

В любое время, когда вы определяете тип delegate, вы определяете класс с методом с именем Invoke и можете использовать синтаксис вызова функции с экземплярами этого класса, что приведет к вызову Invoke. Подобно operator(), делегаты C# Invoke могут иметь почти любую подпись функции.

В отличие от C++ operator(), C# не позволяет определять произвольные другие члены того же класса, который определяет Invoke. Можно сказать, что C# обеспечивает соблюдение принципа единой ответственности. Однако это не является основным ограничением, поскольку делегаты C# подключаются к другому объекту, который обеспечивает хранение состояния для объекта функции.

Более тяжелой (в том смысле, что не существует никакой простой обходной путь) ограничение на C# Invoke по сравнению с С ++ operator() является то, что C# делегат Invoke методы не могут быть перегружены, ни полиморфными. Это является следствием необходимости переадресации вызова методу на другой объект, но это предотвращает использование некоторых сценариев использования с помощью пользовательских функторов C++.

Было бы интересно посмотреть, что произойдет, если вы определили перегруженный метод Invoke с использованием MSIL. Конечно, вы бы смутили компилятор C#, если бы попытались использовать такой класс делегата и, вероятно, также среду CLR. Так что это скорее курионос, чем практический подход.

C++ std::function очень похож на типы делегатов C# в возможностях и ограничениях. Он также переадресовывает вызовы и не является полиморфным по сигнатуре вызова. Ditto для C++ 11 lambdas, хотя C++ 14 lambdas позволит шаблоны operator() и полиморфизм типа call-site (в отличие от C# lambdas, которые допускают только полиморфизм точки определения).

+0

Мне было бы любопытно, что произойдет, если определенный тип делегирования будет определен несколькими методами Invoke. Конечно, такие вещи, как 'Delegate.Combine', были бы полностью обмануты, но мне интересно, будет ли работать' Invoke'. Я действительно желаю, чтобы вместо статических 'Delegate.Combine' и' Delegate.Remove' типы делегатов определили свои собственные методы соединения. Такие методы соединения могут затем либо сгруппировать «Делегат. Комбинация», либо сделать что-то еще, если это необходимо. – supercat

Смежные вопросы