Как я могу использовать классы предопределенных делегатов в 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
}