21

私はすべての匿名機能に不慣れで、助けが必要です。私は次のように動作するようになりました:

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' 型に変換できません** コンパイル エラー。

私は何を間違っていますか?


Mark Ingram が投稿したことから、誰も明示的に言っていませんが、最善の答えのように思えますが、これを行うことです:

public delegate void FakeSave(Transaction t);

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

4 に答える 4

27

これはよく知られているエラー メッセージです。より詳細な議論については、以下のリンクを確認してください。

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

基本的には、匿名デリゲート (ラムダ式) の前にキャストを配置するだけです。

リンクがダウンした場合に備えて、投稿のコピーを次に示します。

これらは匿名メソッドであり、匿名デリゲートではありません。
投稿日: 2007 年 12 月 22 日 by staceyw1

私たちは難しいことをしたいので、それは単なる話題ではありません. 正確に何が起こっているのかを理解するのに役立ちます。明確にするために、匿名デリゲートのようなものはありません。それらは存在しません (まだ)。それらは「匿名メソッド」です – ピリオド。それらをどのように考え、どのように話すかが重要です。匿名メソッド ステートメント "delegate() {…}" を見てみましょう。これは実際には 2 つの異なる操作であり、このように考えると、二度と混乱することはありません。コンパイラが最初に行うことは、推定されたデリゲート シグネチャをメソッド シグネチャとして使用して、内部で匿名メソッドを作成することです。メソッドには名前があり、コンパイラがそれを割り当てるため、メソッドが「名前なし」であると言うのは正しくありません。通常のビューから隠されているだけです。次に行うことは、メソッドをラップするために必要な型のデリゲート オブジェクトを作成することです。これはデリゲート推論と呼ばれ、この混乱の原因となる可能性があります。これが機能するためには、コンパイラは作成するデリゲート型を把握 (つまり、推測) できなければなりません。既知の具象型である必要があります。理由を確認するためにコードを書いてみましょう。

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 行目も同じ理由で機能します。括弧なしで特殊な形式の「デリゲート」を使用したことに注意してください。コンパイラは、キャストからメソッド シグネチャを推測し、推測されたデリゲート型と同じシグネチャを持つ匿名メソッドを作成します。MyMethod() と Action が同じ署名を使用するため、6 行目は機能します。

これが役立つことを願っています。

参照: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/

于 2008-09-12T17:20:21.537 に答える
3

マークが言ったこと。

問題は、Do が Delegate パラメーターを取ることです。コンパイラは、匿名メソッドをデリゲートに変換できません。「デリゲート型」、つまりデリゲートから派生した具象型のみに変換できます。

その Do 関数が Action<>、Action<、> ... などのオーバーロードを受け取った場合、キャストは必要ありません。

于 2008-09-12T17:27:24.950 に答える
1

問題はデリゲート定義ではなく、Do()メソッドのパラメーターがSystem.Delegate型であり、コンパイラーが生成したデリゲート型(FakeSave)が暗黙的にSystem.Delegateに変換されないことです。

匿名のデリゲートの前にキャストを追加してみてください。

Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });
于 2008-09-12T17:47:48.723 に答える
0

次のようなものを試してください:

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);

そのため、デリゲートはトランザクション固有ではありません。

于 2008-09-12T17:07:57.587 に答える