c# - 将此委托(delegate)转换为匿名方法或 lambda

标签 c# .net-3.5 delegates lambda anonymous-methods

我是所有匿名功能的新手,需要一些帮助。我已经得到以下工作:

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 的内部成为一个匿名方法,如果可能的话,甚至是一个 lambda。我试过:

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

但是这些给了我

Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type** compile errors.

我做错了什么?


由于 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/

基本上,您只需要在匿名委托(delegate)(您的 lambda 表达式)前进行强制转换即可。

万一链接失效,这里是帖子的副本:

They are Anonymous Methods, not Anonymous Delegates.
Posted on December 22, 2007 by staceyw1

It 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.

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:

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/

关于c# - 将此委托(delegate)转换为匿名方法或 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59515/

相关文章:

java - C# 从类型创建类的实例

c# - 从相对路径获取绝对URL(重构方法)

delegates - UITextField,1个字符后自动移至下一个

c++ - 如何在Qt中使用委托(delegate)更改图标

c# - List.Sort 方法的二次排序

c# - 如何设置 log4net 使其不记录某些属性?

c# - 存储库是否应该在 Entity Framework 1.0 中使用相同的上下文实例

c# - 如何比较两个对象数组

C# 为什么其中一些使用委托(delegate)和泛型的方法没有启动?

c# - 使用Windows搜索文件API