BadCats
@BadCats

Для этого ли нужны делегаты?

всем привет, только начал изучать делегаты. Имеется вот такой пример:
// Класс, метод которого будет сообщен с делегатом.
    class MyClass
    {
        // Создаем метод, который планируем сообщить с делегатом.
        public string Method(string name)
        {
            return "Hello " + name;
        }
    }

    // На 21-й строке создаем класс-делегата с именем MyDelegate,
    // метод, который будет сообщен с экземпляром данного класса-делегата, 
    // будет принимать один строковой аргумент и возвращать строковое значение.

    public delegate string MyDelegate(string name);  // Создаем класс делегата. (1) 

    class Program
    {
        static void Main()
        {
            MyClass instance = new MyClass();

            MyDelegate myDelegate = new MyDelegate(instance.Method); // Создаем экземпляр делегата и сообщаем с ним метод. (2)
            

           string greeting = myDelegate.Invoke("djon"); // Вызываем метод сообщенный с делегатом. (3)
           

            Console.WriteLine(greeting);

            greeting = myDelegate("Grady Booch"); // Другой способ вызова метода сообщенного с делегатом. (3')

            Console.WriteLine(greeting);

            // Delay.
            Console.ReadKey();
        }
    }

ради интереса заменил строку:
string greeting = myDelegate("djon"); // Вызываем метод сообщенный с делегатом. (3)

на
string greetingg = MyClass.Method("djon");
и получил следующую ошибку от Visual Studio 2012 :
Ошибка 1
Для нестатического поля, метода или свойства "Delegates.MyClass.Method(string)" требуется ссылка на объект

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

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

Если так, то хорошо, если нет то приведите свои жизненные примеры использования делегатов.
  • Вопрос задан
  • 939 просмотров
Решения вопроса 1
Nipheris
@Nipheris Куратор тега C#
Делегаты - это реализация функтора на платформе .net. Функтор - это распространенная в современных языках базовая концепция, пришедшая из функционального программирования. Коротко её смысл в том, чтобы работать с функцией как со значением, наравне со значениями других, более привычных типов, вроде int или double. Т.е. функцию можно передавать в другие функции, возвращать из функций и так далее. В функциональных языках это обычное дело, однако и в императивных языках это даёт массу возможностей.

Количество применений делегатов в дотнете вообще и конкретно в C# огромно. Собственно, сам язык сегодня является частично функциональным из-за того, что широко используются делегаты и основанные на них возможности. Любая лямбда может быть скомпилирована в делегат. LINQ to Objects основаны на делегатах. События есть инкапсулированные делегаты. Любые callback-и в дотнете это делегаты. Список можно продолжать

Сравнивая C# с другими языками, делегаты часто называют "умными указателями на функции" в том смысле, что они похожи на указатели на функции в Си, но умеют еще и запоминать объект, для которого требуется вызвать метод, если метод нестатический. А вот в C++ есть прямой их аналог - это std::function.

В общем, почитайте еще про них. Я даже не понимаю, к чему вы привели свой пример, и что он, по вашему мнению, должен продемонстрировать. Логично, что вы не смогли создать делегат, т.к. инстанс-метод невозможно вызвать без привязки к конкретному объекту.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
arusef
@arusef
Novice .NET dev
Нет, это не жизненный пример. Это вообще очень странный пример, и никто в здравом уме не будет вызывать нестатический метод на имени типа. В данном случае расово верным и единственным рациональным решением было бы обратиться к этому методу, как var ret = instance.Method("string");.

Однако, возвращаясь, собственно, к теме самих делегатов и их жизненного применения. Самым классическим примером была бы реализация функции Where (которая поставляется в LINQ).
// in static class
IEnumerable<TElement> Where(this IEnumerable<TElement> source, Predicate<TElement> filter){
   // для простоты опустим проверки и т.д.
   foreach(TElement elem in source)
      if(filter(elem)) yield return elem;
}
// ... usage ...
var list = new List<int> { 1, 2, 3, 4, 5, 6 };
var ret = list.Where(elem => elem % 2 == 0);
foreach(int e in ret)
   Console.Write(e + " ");
// ...

В данном случае функция перебирает каждый элемент в перечислении source, вызывает функцию filter (функция, которая принимает значение типа TElement и возвращает bool), и возвращает текущий элемент, если возвращённое filter значение было true.
После выполнения фрагмента кода, на экран было бы выведено "2 4 6 ".
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы