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

StackOverflow https://stackoverflow.com/questions/59515

Вопрос

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

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; }));
Это было полезно?

Решение

Это хорошо известное сообщение об ошибке.Перейдите по ссылке ниже для более подробного обсуждения.

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

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

На случай, если ссылка когда-нибудь оборвется, вот копия сообщения:

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

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

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 () и действие используют ту же подпись.

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

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

Другие советы

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

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ:может не работать, поскольку сигнатуры функций EventHandler и делегата не совпадают...Решение, которое вы добавили в конец своего вопроса, может быть единственным способом.

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

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

Так что делегат не зависит от транзакции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top