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

Преобразуйте этот делегат в анонимный метод или лямбда

Я новичок во всех анонимных функциях и нуждаюсь в некоторой помощи. Я получил следующее:

public void FakeSaveWithMessage(Transaction t)
{
    t.Message = "I drink goats blood";
}

public delegate void FakeSave(Transaction t);

public void SampleTestFunction()
{
    Expect.Call(delegate { _dao.Save(t); }).Do(new FakeSave(FakeSaveWithMessage));
}

Но это абсолютно уродливо, и я хотел бы, чтобы внутри Do было анонимным методом или даже лямбдой, если это возможно. Я пробовал:

Expect.Call(delegate { _dao.Save(t); }).Do(delegate(Transaction t2) { t2.Message = "I drink goats blood"; });

и

Expect.Call(delegate { _dao.Save(t); }).Do(delegate { t.Message = "I drink goats blood"; });

но они дают мне

Невозможно преобразовать анонимный метод, чтобы набрать "System.Delegate", потому что это не тип делегата ** компилировать ошибки.

Что я делаю неправильно?


Из-за того, что опубликовал Марк Ингрэм, кажется лучшим ответом, хотя никто прямо не сказал этого, должен сделать это:

public delegate void FakeSave(Transaction t);

Expect.Call(delegate { _dao.Save(t); }).Do( new FakeSave(delegate(Transaction t2) { t.Message = expected_msg; }));
4b9b3361

Ответ 1

Это хорошо известное сообщение об ошибке. Подробнее см. Ссылку ниже.

http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/

В основном вам просто нужно поставить бросок перед вашим анонимным делегатом (ваше лямбда-выражение).

Если ссылка когда-либо опускается, вот копия сообщения:

Они являются анонимными методами, а не Анонимные делегаты.
Опубликовано 22 декабря 2007 по staceyw1

Это не просто точка разговора, потому что мы хотим быть трудными. Это помогает нам причина в том, что именно происходит. Чтобы быть ясным, нет такой вещи как анонимный делегат. Они не есть (не.). Они "Анонимные Методы" - период. мы думаем о них и о том, как мы говорим о их. Давайте взглянем на анонимный оператор метода "delegate() {...}". Это на самом деле два разных операции и когда мы думаем об этом таким образом, мы никогда не будем путать еще раз. Первое, что компилятор is создает анонимный метод под крышками с использованием выведенных подпись делегата как метод подпись. Неверно сказать метод "неназванный", потому что он имеет имя и компилятор назначает его. Он просто скрыт от нормальный вид. Следующее, что он делает создает объект-делегат требуемый тип для обертывания метода. Эта называется делегированием и может быть источником этой путаницы. Для это для работы, компилятор должен быть (то есть вывести), что тип делегата, который он создаст. В нем есть быть известным конкретным типом. Позволять напишите код, чтобы понять, почему.

private void MyMethod()
{
}

Не компилируется:

1) Delegate d = delegate() { };                       // Cannot convert anonymous method to type ‘System.Delegate’ because it is not a delegate type
2) Delegate d2 = MyMethod;                         // Cannot convert method group ‘MyMethod’ to non-delegate type ‘System.Delegate’
3) Delegate d3 = (WaitCallback)MyMethod;   // No overload for ‘MyMethod’ matches delegate ‘System.Threading.WaitCallback’

Строка 1 не компилируется, поскольку компилятор не может вывести любого делегата тип. Он может ясно видеть подпись мы желаем, но нет конкретных тип делегата, который может видеть компилятор. Это может создать анонимный тип введите делегат для нас, но он не работайте так. Строка 2 не скомпилируйте по той же причине. Даже хотя компилятор знает метод подписи, мы не даем ему тип делегата, и это не просто выбрать тот, который будет работать (а не какие побочные эффекты, которые могли бы иметь). Строка 3 не работает, потому что мы намеренно не согласовали метод подпись с делегатом, имеющим другая подпись (как WaitCallback принимает и объект).

Компилирует:

4) Delegate d4 = (MethodInvoker)MyMethod;  // Works because we cast to a delegate type of the same signature.
5) Delegate d5 = (Action)delegate { };              // Works for same reason as d4.
6) Action d6 = MyMethod;                                // Delegate inference at work here. New Action delegate is created and assigned.

Напротив, эти работы. Линия 1 работает потому что мы сообщаем компилятору, что тип делегата для использования, и они соответствуют, поэтому он работает. Строка 5 работает для та же самая причина. Обратите внимание, что мы использовали специальный форма "делегата" без парнеров. Компилятор передает метод подпись от литого и создает анонимный метод с тем же подпись в качестве предполагаемого делегата тип. Строка 6 работает, потому что MyMethod() и Action используют одинаковые подпись.

Надеюсь, это поможет.

Также смотрите: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/

Ответ 2

Что сказал Марк.

Проблема заключается в том, что Do принимает параметр Delegate. Компилятор не может преобразовать анонимные методы в делегат, только "тип делегата", т.е. Конкретный тип, полученный из делегата.

Если в этой функции Do произошла перегрузка Action < > , Action <, > ... и т.д., вам не понадобится приведение.

Ответ 3

Проблема заключается не в определении вашего делегата, а в том, что параметр метода Do() имеет тип System.Delegate и генерируемый компилятором тип делегата (FakeSave) не подразумевает конвертацию в System.Delegate.

Попробуйте добавить бросок перед анонимным делегатом:

Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });

Ответ 4

Попробуйте что-то вроде:

Expect.Call(delegate { _dao.Save(t); }).Do(new EventHandler(delegate(Transaction t2) { t2.CheckInInfo.CheckInMessage = "I drink goats blood"; }));

Обратите внимание на добавленный EventHandler вокруг делегата.

EDIT: может не работать, поскольку сигнатуры функций EventHandler и делегата не совпадают... Решение, добавленное в нижней части вашего вопроса, может быть единственным способом.

В качестве альтернативы вы можете создать общий тип делегата:

public delegate void UnitTestingDelegate<T>(T thing);

Так что делегат не является специфичным для транзакции.