Как я могу использовать классы предопределенных делегатов в C#

Я довольно новичок в программировании и в настоящее время пытаюсь научиться использовать делегаты в C#. Я прочитал руководство по программированию делегатов C# в MSDN и рассмотрел некоторые другие примеры переполнения стека. Я думаю, что я понимаю общую концепцию, но не понимаю, как использовать делегата, который уже определен в классе. Например в Единстве AudioClip класс, есть делегат с именем PCMReaderCallback который вызывается каждый раз, когда аудиоклип читает информацию. Параметры, которые он принимает, это просто массив float ценности.

public delegate void PCMReaderCallback(float[] data);

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

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

Возможно, это невозможно, или, возможно, меня смущает цель делегатов.

2 ответа

У вас есть делегат, объявленный как:

public delegate void PCMReaderCallback(float[] data);

Тогда у вас есть единство AudioClip.Create функция, которая использует этот делегат в качестве параметра. Это единственное, что нужно понять здесь.

Вот как это выглядит:

public static AudioClip Create(string name, int lengthSamples, int channels, int frequency, bool stream, PCMReaderCallback pcmreadercallback);

Как видите, это занимает PCMReaderCallback в качестве параметра, который является именем делегата выше.

Теперь, чтобы использовать его, сначала нужно создать функцию, которая соответствует параметру делегата. Помните, что наш делегат занимает float[] в качестве параметра и является void тип возврата. Это действительно не имеет значения, как вы называете эту функцию. Это должно выглядеть примерно так:

void OnAudioRead(float[] data)
{

}

Наконец, чтобы использовать функцию:

AudioClip newAudioClip = AudioClip.Create("Pigeon", samplerate * 2, 1, samplerate, true, OnAudioRead);
AudioSource attachedSource = GetComponent<AudioSource>();
attachedSource.clip = newAudioClip;
attachedSource.Play();

Как видите, мы прошли в нашем OnAudioRead функция к PCMReaderCallback pcmreadercallback параметр, который будет называть наш OnAudioRead функционировать, когда каждый раз AudioClip читает данные. Это автоматически вызывается Unity.

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

Давайте использовать PCMReaderCallback В качестве примера. PCMReaderCallback объявлен в классе под названием AudioClip, Чтобы использовать его, вы должны использовать полное имя AudioClip.PCMReaderCallback,

Создать функцию, которая принимает AudioClip.PCMReaderCallback в качестве параметра выполните некоторую обработку данных, затем используйте Invoke чтобы вызвать ту функцию, которая передается после завершения обработки:

void makeAlecAudioFunction(AudioClip.PCMReaderCallback allecCallBack)
{
    //Generate some random dummy audio data
    float[] dummyData = new float[4000];
    for (int i = 0; i < dummyData.Length; i++)
    {
        dummyData[i] = Random.Range(0f, 1f);
    }

    //Call the function that was passed in then pass it in the data we generated
    allecCallBack.Invoke(dummyData);
}

Использование этой функции:

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

void OnAlecAudio(float[] data)
{
    for (int i = 0; i < data.Length; i++)
    {
        Debug.Log("Alec Audio Data: " + data[i]);
    }
}

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

makeAlecAudioFunction(OnAlecAudio);

Наконец, я думаю, что основная причина функций обратного вызова заключается в том, чтобы сделать что-то, не заставляя остальную часть программы ждать, а затем выполнить обратный вызов, когда это действие будет выполнено. Из-за этого ваш makeAlecAudioFunction должна быть функцией сопрограммы или должна вызываться в другом Thread (сложный в Unity). При использовании Threadобратный вызов должен быть вызван в основной Thread, Просто пытаюсь сделать этот пример простым.

Делегат - это определенный вами (или другим) тип описания метода. Если вы знакомы с типами Action и Func. Они являются делегатами, определяющими предопределенные типы методов, которые передаются в качестве аргументов.

Например, ваш тип PCMReaderCallback(float[] data), может быть использован в методе так:

public void ProcessData(PCMReaderCallback callback)
{
   List<float> data = new List<float>();
   // generate data here, or load it, etc
   // Then pass the data to the callback.
   callback(data.ToArray());
} 

Так что теперь ProcessData может принимать различные методы с этой подписью. Например,

public void LogData(float[] data)
{
   // write the data to a log file
}

И еще один метод

public void PrintData(float[] data)
{
   foreach(var d in data)
      Console.WriteLine(d.ToString());
}

И вы бы назвали ProcessData как...

ProcessData(LogData); // or...
ProcessData(PrintData);

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

public event PCMReaderCallback DataRead;

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

// read data here
// Then pass to event, first check to see if we have any subscribers.
if (DataRead != null)
{
   // Then prevent race conditions (subscribes and unsubscribes while processing events)
   var Event = DataRead;
   Event(data); // Then call the event here
}
Другие вопросы по тегам