Подтвердить что ты не робот

С# - Как я могу "перегрузить" делегат?

Во-первых, я читал некоторые форумы и помощь в MSDN, и все говорят, что делегат не может быть перегружен.

Теперь я хочу иметь что-то вроде этого:

public delegate void OneDelegate();
public delegate void OneDelegate(params object[] a);

public void DoNothing(params object[] a) {}
public void DoSomething() { /* do something */ }

private OneDelegate someFunction;

someFunction = new OneDelegate(DoSomething);
someFunction = new OneDelegate(DoNothing);

Итак, как вы знаете, вы НЕ МОЖЕТЕ сделать это, потому что OneDelegate относится только к первому, а не ко второму. Но есть ли способ сделать это? или что-то в этом роде?

PS1: У меня не будет никакого количества объявлений OneDelegate, а не только одного или двух.
PS2: Извините за мой плохой английский.

4b9b3361

Ответ 1

Представьте себе, что это было возможно. Предположим, что у меня может быть перегруженный делегат:

public delegate void OneDelegate(int i);
public delegate void OneDelegate(string s);

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

OneDelegate myDelegate = StringMethod;

где StringMethod объявляется следующим образом:

public void StringMethod(string s) { Console.WriteLine(s); }

Теперь вы передаете myDelegate в другой код, и этот код делает это:

myDelegate(47);

Что вы ожидаете в этом случае? Как вызов runtime вызывает StringMethod() с целым аргументом?

Если вы действительно хотите, чтобы делегат мог взять любой набор параметров, единственная опция - иметь один с массивом params object[]:

public delegate void OneDelegate(params object[] parameters);

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

public void MyMethod(params object[] parameters)
{
    if (parameters == null || parameters.Length == 0)
        throw new ArgumentException("No parameters specified.");
    if (parameters.Length > 1)
        throw new ArgumentException("Too many parameters specified.");

    if (parameters[0] is int)
        IntMethod((int) parameters[0]);
    else if (parameters[0] is string)
        StringMethod((string) parameters[0]);
    else
        throw new ArgumentException("Unsupported parameter type.");
}

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

Ответ 2

Действие класс "делает это". Это делегат с шаблонами, поэтому у вас может быть такой делегат:

public delegate void D<T>(params T[] arg);

func() {
    D<object> d1;
}

Это, вероятно, так близко, как вы собираетесь получить, т.е. вам нужен тип шаблона в качестве параметра.

Изменить: основываясь на комментариях, я думаю, вы после передачи делегата другой функции. Вы можете выполнить это, пройдя также аргументы. К сожалению, вы не можете сделать это без использования параметра params до fire.

public void bar() {
    D<string> d = ...;
    fire(d, "first", "second");
    fire(d); // also works
}

public void fire<T>(D<T> f, params T[] args) {
    f(args);
}