C# делегирует методы с различными необязательными параметрами

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

delegate void MyDelegate(int x, int y = 5);

а затем вызывать его в любом месте любым методом, который соответствует сигнатуре.

Хорошо, у меня есть МНОГО методов, объявленных таким образом:

public Something FirstMethod(float val = 10, int skip = 0){ ... return sth; }
public Something SecondMethod(float val = 20, int skip = 0){ ... return sth; }
public Something ThirdMethod(float val = 5, int skip = 0){ ... return sth; }

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

Затем я хочу создать делегат, который будет указывать на один из этих методов:

delegate Something ProblematicDelegateType(<<WHAT WILL GO HERE>>);
ProblematicDelegateType myFunc;
if(someValue == someParameter){
    myFunc = FirstMethod;
}else if(...){
    myFunc = SecondMethod;
}else...
...
}

myFunc();
myFunc(skip:100);

Я хочу иметь возможность вызывать myFunc как без параметров, так и с параметром skip. В этой части кода первый параметр val НЕ используется. (они используются в другом месте).

Что войдет в список аргументов делегата? Я хочу сохранить аргумент val этого метода по умолчанию, каким бы он ни был.


person Can Poyrazoğlu    schedule 17.08.2011    source источник


Ответы (3)


Если я вас правильно понял, ваш myFunc полностью исключит параметр val, всегда используя значение по умолчанию для любого метода, который вы в конечном итоге вызываете, верно?

Если это так, это должно выполнить то, что вы ищете:

delegate Something ProblematicDelegateType(int skip = 0);
ProblematicDelegateType myFunc;
if (someValue == someParameter) {
    myFunc = skip => FirstMethod(skip: skip);
} else if (...) {
    myFunc = skip => SecondMethod(skip: skip);
} else ...
    ...
}
person Joe White    schedule 17.08.2011
comment
это работает, но есть ли лучший, более формальный/модульный способ сделать это? Я ищу что-то, что я не добавляю skip => Method(skip:skip); и просто могу «каким-то образом» вызвать метод, указанный myFunc напрямую, без оборачивания другой лямбды. конечно, если это возможно :) - person Can Poyrazoğlu; 18.08.2011
comment
@can poyrazoğlu: Это невозможно. Методы FirstMethod, SecondMethod и т. д. должны вызываться явно где-нибудь, если вы хотите использовать некоторые аргументы по умолчанию, потому что только в этих местах вызова аргументы по умолчанию вставляются компилятором. Так что единственный способ - обернуть их - person JBSnorro; 18.08.2011
comment
хорошо, тогда я продолжу с обертыванием. но все же не удивляйтесь, почему это нельзя сделать, так как сигнатура "жестко закодирована", нигде нет дженериков или приведений типов, и если компилятор знает точный порядок и тип параметров, то логически должен быть способ в это. но я все равно буду использовать обертку. - person Can Poyrazoğlu; 18.08.2011
comment
Поскольку необязательные аргументы определяются во время компиляции, а не во время выполнения. Когда вы пишете MyDelegate(1); компилятор генерирует вызов MyDelegate(1, 5); Он не знает, каким будет фактический делегат во время выполнения. - person Kyle W; 18.08.2011

Используйте лямбду, чтобы связать нужное значение. Значения по умолчанию фактически являются перегрузками, которые связывают желаемое значение с параметром функции. Поскольку у вас есть различные if, разделяющие функции, просто передайте делегата функции, которая принимает только целое число.

Другими словами,

delegate Something ProblematicDelegateType(int skip = 0)

//...

ProblematicDelegateType myDelegate;
if (someCondition)
  myDelegate = (_1) => FirstMethod(10, _1);
else if (someOtherCondition)
  myDelegate = (_1) => SecondMethod(20, _1);

и так далее..

person ex0du5    schedule 17.08.2011
comment
проблема в том, что я не хочу касаться другого аргумента (первого) метода, который я вызываю. - person Can Poyrazoğlu; 18.08.2011

Ваше требование, чтобы делегат имел необязательный параметр, который зависит от метода, который он вызывает, не может быть выполнен. Необязательные параметры реализуются путем перезаписи места вызова метода при его компиляции. Если метод, на который указывает делегат, определяется во время выполнения, что он будет писать во время компиляции? Серия Эрика Липперта на тему необязательные аргументы очень поучительны.

Однако вы также можете использовать отражение, чтобы получить значение по умолчанию. Используйте MethodInfo.GetParameters() для получения сведений о параметрах и ParameterInfo.DefaultValue. чтобы получить значение по умолчанию.

person Mike Zboray    schedule 18.08.2011
comment
Теперь я понимаю ... но я не хочу вдаваться в размышления, я бы просто выбрал решение-оболочку. - person Can Poyrazoğlu; 18.08.2011