Являются ли делегаты не просто стенографическими интерфейсами? - PullRequest
10 голосов
/ 18 сентября 2008

Предположим, у нас есть:

interface Foo 
{
 bool Func(int x);
}

class Bar: Foo
{
  bool Func(int x)
  {
   return (x>0);
  }  
}

class Baz: Foo
{
  bool Func(int x)
  {
   return (x<0);
  }  
}

Теперь мы можем перебирать Bar и Baz как Foos и вызывать их методы Func.

Делегаты немного упрощают это:

delegate bool Foo(int x);

bool Bar(int x)
{
 return (x<0);
}

bool Baz(int x)
{
 return (x>0);
}

Теперь мы можем метаться вокруг Бар и Баз в качестве делегатов Foo.

Какая реальная выгода для делегатов, кроме получения более короткого кода?

Ответы [ 10 ]

14 голосов
/ 18 сентября 2008

Есть небольшая разница, делегаты могут получить доступ к переменным-членам классов, в которых они определены. В C # (в отличие от Java) весь внутренний класс считается статическим. Поэтому, если вы используете интерфейс для управления обратным вызовом, например, ActionListener для кнопки. Внутреннему классу реализации необходимо передать (через конструктор) ссылки на части содержащего класса, с которыми ему может потребоваться взаимодействовать во время обратного вызова. Делегаты не имеют этого ограничения, поэтому уменьшают количество кода, необходимого для реализации обратного вызова.

Короче, более краткий код также является достойным преимуществом.

6 голосов
/ 18 сентября 2008

С точки зрения разработки программного обеспечения вы правы, делегаты во многом похожи на интерфейсы функций в том смысле, что они создают прототип интерфейса функций.

Они также могут использоваться во многом аналогичным образом: вместо передачи целого класса, содержащего необходимый метод, вы можете передать только делегат. Это экономит много кода и создает намного более читаемый код.

Более того, с появлением лямбда-выражений их теперь можно легко определять на лету, что является огромным бонусом. Хотя ВОЗМОЖНО создавать классы на лету в C #, это действительно огромная боль в заднице.

Сравнение двух - интересная концепция. Ранее я не думал, насколько похожи идеи с точки зрения варианта использования и структурирования кода.

3 голосов
/ 18 сентября 2008

Делегат имеет много общего с интерфейсной ссылкой, которая имеет один метод с точки зрения вызывающей стороны.

В первом примере Baz и Bar являются классами, которые могут наследоваться и создаваться. Во втором примере Baz и Bar являются методами.

Нельзя применять ссылки на интерфейсы только к любому классу, который соответствует контракту интерфейса. Класс должен явно объявить, что он поддерживает интерфейс. Вы можете применить ссылку делегата к любому методу, который соответствует подписи.

Вы не можете включать статические методы в контракт интерфейса. (Хотя вы можете использовать статические методы с помощью методов расширения). Вы можете ссылаться на статические методы с помощью ссылки на делегат.

1 голос
/ 18 сентября 2008

Можно рассматривать делегатов как интерфейс для метода, который определяет, какие аргументы и тип возвращаемого значения должен иметь метод, чтобы соответствовать делегату

1 голос
/ 18 сентября 2008

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

1 голос
/ 18 сентября 2008

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

Кроме того, тогда вам не нужно знать структуру класса. Таким образом, вы можете использовать метод, который вы написали, чтобы передать в метод в другом классе, и определить функциональность, которую вы хотите иметь.

Посмотрите на класс List <> с помощью метода Find . Теперь вы можете определить, что определяет, является ли что-то совпадением или нет, не требуя элементов, содержащихся в классе, для реализации IListFindable или чего-то подобного.

0 голосов
/ 05 марта 2009

По крайней мере в одном предложении о добавлении замыканий (то есть анонимных делегатов) в Java они эквивалентны интерфейсам с одним методом-членом.

0 голосов
/ 18 сентября 2008

Интерфейсы и делегаты - это две совершенно разные вещи, хотя я понимаю соблазн описывать делегатов в терминах, подобных интерфейсам, для простоты понимания ... однако, незнание правды может привести к путанице.

Делегаты были воодушевлены (частично) из-за того, что черное искусство указателей методов C ++ не подходит для определенных целей. Классическим примером является реализация механизма передачи сообщений или обработки событий. Делегаты позволяют вам определять сигнатуру метода без знания типов или интерфейсов класса - я мог бы определить делегат void eventHandler (Event * e) и вызывать его для любого класса, который его реализовал.

Чтобы получить представление об этой классической проблеме и о том, почему желательны делегаты , прочитайте это , а затем это .

0 голосов
/ 18 сентября 2008

Да, делегата можно рассматривать как интерфейс с одним методом.

0 голосов
/ 18 сентября 2008

Делегат - это указатель на типизированный метод. Это дает вам больше гибкости, чем интерфейсы, потому что вы можете использовать ковариацию и контравариантность и изменять состояние объекта (вам придется передавать указатель this с помощью функторов на основе интерфейса).

Кроме того, у делегатов есть много приятного синтаксического сахара, который позволяет вам легко комбинировать их вместе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...