Сделать метод C # "реализовать" делегат - PullRequest
4 голосов
/ 16 марта 2012

Кто-нибудь знает способ в C # заставить метод "реализовать" делегат?

Рассмотрим этот сильно упрощенный пример: (слабо основанный на сценарии реального мира, с которым я столкнулся)

    private delegate int ComputationMethod(int termA, int termB, int termC, int termD);

    private int computationHelper(int termA, int termB, int termC, int termD, ComputationMethod computationMethod)
    {
        //Some common logic^
        int answer = computationMethod(termA, termB, termC, termD);
        //Some more common logic^
        return answer;
    }

    public int ComputeAverage(int termA, int termB, int termC, int termD)
    {
        //^^
        return computationHelper(termA, termB, termC, termD, computeAverage);
    }

    public int ComputeStandardDeviation(int termA, int termB, int termC, int termD)
    {
        //^^
        return computationHelper(termA, termB, termC, termD, computeStandardDeviation);
    }        

    //Is there some way to force this method's signature to match ComputationMethod?
    private static int computeAverage(int termA, int termB, int termC, int termD) 
    {
        //Implementation omitted
    }

    //Is there some way to force this method's signature to match ComputationMethod?
    private static int computeStandardDeviation(int termA, int termB, int termC, int termD)
    {
        //Implementation omitted
    }

^ - Предположим, что эта логика не может быть вызвана из ^^.

В этом примере я, по сути, хотел бы «заставить» методы соответствовать сигнатуре ComputationMethod таким же образом, как интерфейс вынуждает класс реализовывать определенные методы. Нечто эквивалентное:

private static int computeAverage(int termA, int termB, int termC, int termD) : ComputationMethod
    {
        //Implementation omitted
    }

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

Спасибо за любую помощь.

Ответы [ 3 ]

4 голосов
/ 16 марта 2012

C # не поддерживает это.

Однако вы можете смоделировать его, просто поместив метод в делегат:

static readonly ComputationMethod _ForceCompliance = ComputeAverage;
private static int ComputeAverage(int termA, int termB, int termC, int termD) { ... }

Изменение метода или подписи делегата может привести к ошибке компиляции на одну строку выше метода.

(выполнение этого с методами экземпляра потребует вызова конструктора)

Для повышения эффективности вы можете сделать это в неиспользуемом вложенном классе и / или в #if DEBUG.

В любом случае, оставьте пояснительный комментарий.

4 голосов
/ 16 марта 2012

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

Это методы, которые вы запрашиваетео static не имеет значения.

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

0 голосов
/ 16 марта 2012

Если вам не требуется использование делегатов, вы можете использовать следующий шаблон:

public interface IComputationMethod
{
    int ComputationMethod(int termA, int termB, int termC, int termD);
}

public class AverageComputer : IComputationMethod
{
    public override int ComputationMethod(int termA, int termB, int termC, int termD)
    {
    // omitted.
    }
}

public class StDevComputer : IComputationMethod
{
    public override int ComputationMethod(int termA, int termB, int termC, int termD)
    {
    // omitted.
    }
}

И изменить подпись помощника по вычислениям на:

private int computationHelper(int termA, int termB, int termC, int termD, IComputationMethod computation)
{
    //Some common logic^
    int answer = computation.ComputationMethod(termA, termB, termC, termD);
    //Some more common logic^
    return answer;
}
...