質問

私は匿名機能を初めて使用するので、助けが必要です。以下が機能するようになりました。

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; }));
役に立ちましたか?

解決

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

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

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

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

それらは匿名のメソッドであり、匿名の代表者ではありません。
投稿日: 2007 年 12 月 22 日、作成者: 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()とアクションが同じ署名を使用するため、6行目は機能します。

これがお役に立てば幸いです。

以下も参照してください。 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