C# 将此委托转换为匿名方法或 lambda
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/59515/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert this delegate to an anonymous method or lambda
提问by George Mauer
I am new to all the anonymous features and need some help. I have gotten the following to work:
我是所有匿名功能的新手,需要一些帮助。我已经得到以下工作:
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));
}
But this is totally ugly and I would like to have the inside of the Do to be an anonymous method or even a lambda if it is possible. I tried:
但这完全是丑陋的,如果可能的话,我希望 Do 的内部成为一个匿名方法,甚至是一个 lambda。我试过:
Expect.Call(delegate { _dao.Save(t); }).Do(delegate(Transaction t2) { t2.Message = "I drink goats blood"; });
and
和
Expect.Call(delegate { _dao.Save(t); }).Do(delegate { t.Message = "I drink goats blood"; });
but these give me
但这些给了我
Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type** compile errors.
无法将匿名方法转换为类型“System.Delegate”,因为它不是委托类型**编译错误。
What am I doing wrong?
我究竟做错了什么?
Because of what Mark Ingram posted, seems like the best answer, though nobody's explicitly said it, is to do this:
由于马克英格拉姆发布的内容,尽管没有人明确表示,但似乎最好的答案是这样做:
public delegate void FakeSave(Transaction t);
Expect.Call(delegate { _dao.Save(t); }).Do( new FakeSave(delegate(Transaction t2) { t.Message = expected_msg; }));
采纳答案by Mark Ingram
That's a well known error message. Check the link below for a more detailed discussion.
这是一个众所周知的错误信息。查看下面的链接以获得更详细的讨论。
http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/
http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/
Basically you just need to put a cast in front of your anonymous delegate (your lambda expression).
基本上你只需要在你的匿名委托(你的 lambda 表达式)前面放一个演员表。
In case the link ever goes down, here is a copy of the post:
万一链接失效,这里是帖子的副本:
They are Anonymous Methods, not Anonymous Delegates.
Posted on December 22, 2007 by staceyw1It is not just a talking point because we want to be difficult. It helps us reason about what exactly is going on. To be clear, there is *no such thing as an anonymous delegate. They don't exist (not yet). They are "Anonymous Methods" – period. It matters in how we think of them and how we talk about them. Lets take a look at the anonymous method statement "delegate() {…}". This is actually two different operations and when we think of it this way, we will never be confused again. The first thing the compiler does is create the anonymous method under the covers using the inferred delegate signature as the method signature. It is not correct to say the method is "unnamed" because it does have a name and the compiler assigns it. It is just hidden from normal view. The next thing it does is create a delegate object of the required type to wrap the method. This is called delegate inference and can be the source of this confusion. For this to work, the compiler must be able to figure out (i.e. infer) what delegate type it will create. It has to be a known concrete type. Let write some code to see why.
它们是匿名方法,而不是匿名委托。
2007 年 12 月 22 日,staceyw1 发表这不仅仅是一个话题,因为我们想要变得困难。它帮助我们推理到底发生了什么。需要明确的是,*没有匿名委托这样的东西。它们不存在(还没有)。它们是“匿名方法”——时期。重要的是我们如何看待它们以及我们如何谈论它们。让我们来看看匿名方法语句“delegate() {…}”。这实际上是两种不同的操作,当我们这样想时,我们再也不会混淆了。编译器做的第一件事是使用推断的委托签名作为方法签名在幕后创建匿名方法。说该方法“未命名”是不正确的,因为它确实有一个名称并且编译器分配了它。它只是隐藏在正常视图中。它接下来要做的是创建一个所需类型的委托对象来包装方法。这称为委托推理,可能是这种混淆的根源。为此,编译器必须能够确定(即推断)它将创建的委托类型。它必须是已知的具体类型。让我们写一些代码看看为什么。
private void MyMethod()
{
}
Does not compile:
不编译:
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'
Line 1 does not compile because the compiler can not infer any delegate type. It can plainly see the signature we desire, but there is no concrete delegate type the compiler can see. It could create an anonymous type of type delegate for us, but it does not work like that. Line 2 does not compile for a similar reason. Even though the compiler knows the method signature, we are not giving it a delegate type and it is not just going to pick one that would happen to work (not what side effects that could have). Line 3 does not work because we purposely mismatched the method signature with a delegate having a different signature (as WaitCallback takes and object).
Compiles:
第 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.
In contrast, these work. Line 1 works because we tell the compiler what delegate type to use and they match, so it works. Line 5 works for the same reason. Note we used the special form of "delegate" without the parens. The compiler infers the method signature from the cast and creates the anonymous method with the same signature as the inferred delegate type. Line 6 works because the MyMethod() and Action use same signature.
I hope this helps.
Also see: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/
相比之下,这些工作。第 1 行之所以起作用,是因为我们告诉编译器要使用哪种委托类型并且它们匹配,所以它起作用了。第 5 行的工作原理相同。请注意,我们使用了没有括号的特殊形式的“委托”。编译器从转换中推断方法签名,并创建与推断的委托类型具有相同签名的匿名方法。第 6 行有效,因为 MyMethod() 和 Action 使用相同的签名。
我希望这有帮助。
回答by Chris Marasti-Georg
Try something like:
尝试类似:
Expect.Call(delegate { _dao.Save(t); }).Do(new EventHandler(delegate(Transaction t2) { t2.CheckInInfo.CheckInMessage = "I drink goats blood"; }));
Note the added EventHandler around the delegate.
请注意在委托周围添加的 EventHandler。
EDIT: might not work since the function signatures of EventHandler and the delegate are not the same... The solution you added to the bottom of your question may be the only way.
编辑:可能不起作用,因为 EventHandler 和委托的函数签名不一样......您添加到问题底部的解决方案可能是唯一的方法。
Alternately, you could create a generic delegate type:
或者,您可以创建一个通用委托类型:
public delegate void UnitTestingDelegate<T>(T thing);
So that the delegate is not Transaction specific.
这样委托就不是特定于事务的。
回答by hwiechers
What Mark said.
马克说的。
The problem is that Do takes a Delegate parameter. The compiler can't convert the anonymous methods to Delegate, only a "delegate type" i.e. a concrete type derived from Delegate.
问题是 Do 需要一个 Delegate 参数。编译器不能将匿名方法转换为委托,只能转换为“委托类型”,即从委托派生的具体类型。
If that Do function had took Action<>, Action<,> ... etc. overloads, you wouldn't need the cast.
如果那个 Do 函数接受了 Action<>, Action<,> ... 等重载,你就不需要演员表了。
回答by Brannon
The problem is not with your delegate definition, it's that the parameter of the Do() method is of type System.Delegate, and the compiler generated delegate type (FakeSave) does not implicitly convert to System.Delegate.
问题不在于您的委托定义,而是 Do() 方法的参数属于 System.Delegate 类型,并且编译器生成的委托类型 (FakeSave) 不会隐式转换为 System.Delegate。
Try adding a cast in front of your anonymous delegate:
尝试在匿名委托前添加演员表:
Expect.Call(delegate { _dao.Save(t); }).Do((Delegate)delegate { t.Message = "I drink goats blood"; });