Какова цель делегатов в .NET - PullRequest
2 голосов
/ 07 октября 2011

Так что я немного запутался по поводу делегатов в C # .... что они делают и чем они полезны?Я прочитал несколько учебных пособий, и я не совсем понимаю, что они должны делать (каждый связывает их с указателями на функции в C, и я никогда не программировал на C).

Итак ... что делают делегаты?В каком сценарии я должен их использовать?Как бы я их потом использовал?

Ответы [ 7 ]

6 голосов
/ 07 октября 2011

Другие ответы хороши, но вот еще один способ подумать о делегатах, которые могут помочь.Представьте, что делегат - не более чем интерфейс.Когда вы видите:

delegate void Action();

думаете:

interface IAction
{
    void Invoke();
}

И когда вы видите:

Action myAction = foo.Bar;

думаете:

class FooBarAction : IAction
{
    public Foo Receiver { get; private set; }
    public FooBarAction(Foo foo)
    {
        this.Receiver = foo;
    }
    public void Invoke()
    {
        this.Receiver.Bar();
    }
}
...
IAction myAction = new FooBarAction(foo);

Икогда вы видите

myAction();

думайте

myAction.Invoke();

Фактические детали того, какие типы создаются, немного отличаются, но в основном это то, что происходит.Делегат - это просто объект с методом Invoke, и когда вы вызываете этот метод, он вызывает какой-то другой метод для другого объекта от вашего имени .Вот почему он называется «делегат» - потому что он делегирует вызов другого метода другого объекта.

4 голосов
/ 07 октября 2011

Делегаты - это что-то вроде объектов, представляющих вызов метода.Один полезный способ их использования - обратные вызовы.Например, представьте, что у вас есть метод, который делает что-то асинхронное, и вы хотите, чтобы вызывающая сторона могла указывать, что он хочет произойти после его завершения (Action тип делегата):

public void DoSomething(Action whatToDoWhenDone)
{
    // Your code

    // See how the delegate is called like a method
    whatToDoWhenDone();
}

Пользователь DoSomething теперь может указывать обратный вызов в качестве параметра:

public void AnotherMethod()
{
    DoSomething(ShowSuccess); // ShowSuccess will be called when done
}

public void ShowSuccess()
{
    Console.WriteLine("Success!");
}

Вы также можете использовать выражения lamba в качестве более короткого способа написания своего делегата:

public void AnotherMethod()
{
    DoSomething(() => Console.WriteLine("Success!"));
    // Also DoSomething(delegate() { Console.WriteLine("Success!"); });
}

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

1 голос
/ 07 октября 2011

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

// This is the delegate for a function that takes a string and returns a string.
// It can also be written using the framework-provided Generic delegate Func, as
// Func<String, String>
delegate String StringToStringDelegate(String input);

Вы можете определить переменную этого типа и назначить еек существующему методу.Я использую универсальный в качестве примера, потому что это более распространенное использование в .net начиная с 2.0:

String Reverse(String input) {
    return input.Reverse();
}

Func<String, String> someStringMethod = new Func<String, String>(Reverse);

// Prints "cba":
Console.WriteLine(someStringMethod("abc"));

Вы также можете передавать функции следующим образом:

String Reverse(String input) {
    return input.Reverse();
}

String UpperCase(String input) {
    return input.ToUpper();
}

String DoSomethingToABC(Func<String, String> inputFunction) {
    return inputFunction("abc");
}

var someStringMethod = new Func<String, String>(Reverse);

// Prints "cba":
Console.WriteLine(DoSomethingToABC(someStringMethod));

var someOtherStringMethod = new Func<String, String>(UpperCase);

// Prints "ABC":
Console.WriteLine(DoSomethingToABC(someOtherStringMethod));
0 голосов
/ 07 октября 2011

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

Например,

 public delegate void AnEmptyVoidFunction();

Это создает тип делегата с именем AnEmptyVoidFunctionи его можно использовать для хранения ссылок на функции, которые возвращают void и не имеют аргументов.

Затем можно сохранить ссылку на функцию с этой подписью.

public static void SomeMethod() { }
public static int ADifferentMethod(int someArg) { return someArg; }

AnEmptyVoidFunction func1 = new AnEmptyVoidFunction(SomeMethod);
// or leave out the constructor call to let the compiler figure it out
AnEmptyVoidFunction func2 = SomeMethod;
// note that the above only works if it is a function defined
// within a class, it doesn't work with other delegates

//AnEmptyVoidFunction func3 = new AnEmptyVoidFunction(ADifferentMethod);
                              // error wrong function type

Мало того, что она можетхранить объявленные функции, но также и анонимные функции (т. е. лямбды или анонимные делегаты)

// storing a lambda function (C#3 and up)
AnEmptyVoidFunction func4 = () => { };

// storing an anonymous delegate (C#2)
AnEmptyVoidFunction func5 = delegate() { };

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

AnEmptyVoidFunction func1 = () =>
{
    Console.WriteLine("Hello World");
};
func1(); // "Hello World"

AnEmptyVoidFunction func2 = null;
func2(); // NullReferenceException

public static void CallIt(AnEmptyDelegate func)
{
    // check first if it is not null
    if (func != null)
    {
        func();
    }
}

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

0 голосов
/ 07 октября 2011

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

Обработчик событий - это специальный тип делегата. Например, делегат обработчика события может ответить на событие, такое как щелчок мыши или нажатие клавиши. События на сегодняшний день являются наиболее распространенным типом делегата. Фактически, вы обычно увидите, что ключевое слово события используется в коде C # гораздо чаще, чем ключевое слово делегата.

0 голосов
/ 07 октября 2011

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

Причина, по которой люди связывают делегатов с указателями на функции C, заключается в том, что по сути это и есть делегирование, т. Е. Указатели на методы.

Например:

public void DoSomething(Action yourCodeBlock)
{
    yourCodeBlock();
}

public void CallingMethod()
{
    this.DoSomething(
    {
        ... statements
    });

    this.DoSomething(
    {
        ... other statements
    });
}

ТамЕстественно, есть много способов вызвать делегатов, так как все уроки покажут вам.Дело в том, что это позволяет вам «делегировать» функциональность таким образом, что вы можете вызывать методы, не обязательно зная, как они работают, а просто полагая, что о них позаботятся.Другими словами, я мог бы создать класс, который реализует функцию «DoSomething ()», но я могу предоставить кому-то другому возможность решать, что будет делать DoSomething () позже.

Надеюсь, это поможет.: -)

0 голосов
/ 07 октября 2011

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

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