Создание и передача пользовательской функции в качестве делегата (VB.NET 2005) - PullRequest
0 голосов
/ 05 августа 2009

У меня есть функция Process(data, f), где data - нормальный параметр, а f - функция, необходимая для обработки данных (переданных в качестве делегата Process)

Подпись f равна int f(a,b,c), причем a, b, c предоставлены Process при вызове делегата.

Вплоть до здесь, стандартное использование делегата.

Теперь у меня есть особый, но распространенный случай, когда я хотел бы вызвать Process с постоянной функцией f. Поэтому я хотел бы написать SimpleProcess(data, k), чтобы вызывающему абоненту не нужно было создавать делегата в этом случае, просто передайте константу k (единственная необходимая информация).

Так что мне нужно динамически создать постоянную функцию, g(a,b,c), которая принимает 3 параметра (которые игнорируются) и всегда возвращает k. Это должно быть сделано в функции SimpleProcess, чтобы я мог просто вызвать Process(data, g) из этой функции, без необходимости переписывать всю функцию Process для этого особого случая.

Возможно ли это, и как мне этого добиться?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 05 августа 2009

РЕДАКТИРОВАТЬ: Хорошо, я не заметил бит "2005" в названии. Мой оригинальный ответ позже (под линией) - вот полный ответ для VB.NET 2005.

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

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

Public Delegate Function Function3 (ByVal x As Integer, _
    ByVal y As Integer, ByVal z As Integer) As Integer

Public Class Constant

    Private value As Integer

    Public Sub New (ByVal value As Integer)
      Me.value = value    
    End Sub

    Public Function ReturnValue(ByVal x As Integer, _
        ByVal y As Integer, ByVal z As Integer) _
        As Integer
      Return value
    End Function

    Public Shared Function CreateFunction _
        (ByVal x As Integer) As Function3    
      Dim c As Constant = New Constant(x)
      return AddressOf c.ReturnValue
    End Function

End Class

Public Module Test
    Public Sub Main
      Dim func As Function3 = Constant.CreateFunction(3)
      Console.WriteLine(func(8, 9, 10))
    End Sub
End Module

В вашем случае вы бы использовали его с:

Process(data, Constant.CreateFunction(g))

Оригинальный ответ

Вы можете использовать лямбда-выражение, хотя с тремя параметрами это будет не очень приятно:

Process(data, Function(x as Integer, y as Integer, z as Integer) g)

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

Public Function Constant(value as Integer) As MyDelegateType
    Return Function(x as Integer, y as Integer, z as Integer) value
End Function

Затем назовите его с помощью:

Process(data, Constant(g))

Извиняюсь, если какой-то синтаксис слегка выключен - я действительно не VB человек.

0 голосов
/ 03 ноября 2010

Подход, который может показаться устаревшим, учитывая, что более новые языки поддерживают лямбда-выражения, заключается в создании некоторых общих классов фабрик делегатов. Я не сделал этого для функций трех переменных параметров, но подход был бы легко адаптируем для такого. Подход похож на ответ @Jon Skeet: выше, но для использования одной из моих общих фабрик (если бы я расширил ее до трех переменных плюс один фиксированный параметр), вам нужно было бы определить функцию, которая принимает четыре параметра и просто возвращает последний, а затем создает желаемый делегат (для значения, например, 19) с

  Process(data, FunctionOf(of Integer, Integer, Integer, Integer).NewInv(of Integer)(AddressOf FunctionToReturnLastValue, 19))

Обратите внимание, что в отличие от лямбда-выражений, приведенный выше код может быть добавлен, изменен или удален без аннулирования редактирования и продолжения (обратите внимание, что последний (из Integer), вероятно, может быть выведен). Кроме того, в отличие от лямбд, значения фиксированных параметров оцениваются при создании делегата, а не при его вызове.

0 голосов
/ 05 августа 2009

Рассматривали ли вы разделение функции на две части с разными сигнатурами. Я предполагаю, что ваша функция делегата вернет значение, которое предоставляет константа.

Таким образом, ваша версия метода делегата будет просто выполнять обработку, необходимую для вычисления «постоянного» значения.

    Function Process(ByVal data As Object, ByVal f As MyDelegate) As Object
    Dim k As Integer
    ' Calculate k

    Return Process(data, k)
End Function

Function Process(ByVal data As Object, ByVal k As Integer) As Object
    Dim stuff As Object

    ' do stuff with k
    Return stuff
End Function

Delegate Function MyDelegate(ByVal a As Object, ByVal b As Object, ByVal c As Object) As Integer
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...