【问题标题】:How can I write the following callback continuations in c# lambda syntax?如何在 c# lambda 语法中编写以下回调延续?
【发布时间】:2011-11-22 02:27:16
【问题描述】:

我正在编写一个异步单元测试,我想使用 lambdas(或匿名方法?)将它串在一起,因此我不必为延续定义命名函数。

我已经阅读了几篇关于 lambdas 的帖子,但是 mostthese 处理我不感兴趣的每种样式构造。

我想做类似以下的事情(取自here):

using Microsoft.Silverlight.Testing;  
using Microsoft.VisualStudio.TestTools.UnitTesting;  
{  
    [TestClass]  
    public class Test2 : SilverlightTest  
    {  
        [TestMethod]  
        [Asynchronous]  
        public void TestAsync1()  
        {  
            var eventRaised = false;  
            var result = false;  
            var timer = new System.Windows.Threading.DispatcherTimer();  

            timer.Interval = TimeSpan.FromSeconds(2);  
            timer.Tick += (object sender, EventArgs e) =>  
                {  
                    timer.Stop();  

                    // Simulate an expected result  
                    result = true;  

                    // Mark the event has being raised  
                    eventRaised = true;  
                };  

            // Start timer  
            EnqueueCallback(() => timer.Start());  

            // Wait until event is raised  
            EnqueueConditional(() => eventRaised);  
            EnqueueCallback(() =>  
            {  
                // Additional tasks can be added here  
                Assert.IsTrue(result);  
            });  

            EnqueueTestComplete();  
        }  
    }  
}  

但我想我不需要 EnqueueCallback() 的东西。

以下是我没有 lambdas 的代码:

[TestClass]
public class IdentityEditDatabaseTest : WorkItemTest
{
  [TestMethod, Asynchronous] public void testNullInsert()
  {
    wipeTestData(testNullInsertContinue1);
  }
  private void testNullInsertContinue1(String errorString)
  {
    IdentityProperties properties = new IdentityProperties(getContext());
    properties.setUserName(DATABASE_TEST);
    postUserEdit(properties, testNullInsertContinue2);
  }
  private void testNullInsertContinue2(String errorString)
  {
    Assert.assertTrue(errorString == null);

    wipeTestData(testNullInsertContinue3);
  }
  private void testNullInsertContinue3(String errorString)
  {
    TestComplete();
  }
}

...

再次,问题是:

如何使用 lambda(或匿名方法?)将上述内容串在一起,这样我就不必为延续定义命名函数?

请尽可能多地解释新语法,因为我仍在努力理解这个概念。

非常感谢!

【问题讨论】:

  • 我可能完全是愚蠢的,也许我没有理解这个问题(看起来很难),但是你为什么不订阅 timer.Tick 事件呢?

标签: c# lambda


【解决方案1】:

如果我们有以下方法:

private void DoSomething(object argument)
{
    // Do something with the argument here
}

您可能知道它可以像这样分配给委托变量:

Action<object> asDelegate = DoSomething;

要使用匿名方法进行同样的赋值,我们可以使用 lambda 表达式:

Action<object> asDelegate = (object argument) =>
    {
        // Do something with the argument here
    }

所以在你的例子中,方法 testNullInsert 可以这样写:

[TestMethod, Asynchronous]
public void testNullInsert()
{
    wipeTestData((string errorString) =>
    {
        IdentityProperties properties = new IdentityProperties(getContext());
        properties.setUserName(DATABASE_TEST);
        postUserEdit(properties, testNullInsertContinue2);
    });
}

我在那里所做的所有事情都将名称 testNullInsertContinue1 替换为包含相同功能的 lambda 表达式。如果你愿意,你也可以用 testNullInsertContinue2 做同样的事情。

一旦你更熟悉了 lambda 表达式的使用,你可以去掉参数周围的括号(如果只有一个参数)和参数的类型,因为编译器通常可以推断它们,但我已经写了像这样试图让你尽可能地了解正在发生的事情。希望这会有所帮助。

【讨论】:

  • 谢谢,这完美地回答了我的问题。不幸的是,我将无法使用这种方法,因为这意味着我每次链接 lambda 时都需要重命名变量“errorString”以避免 CS0136 :(
猜你喜欢
  • 2020-06-20
  • 2010-10-30
  • 2017-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-24
  • 1970-01-01
  • 2015-05-26
相关资源
最近更新 更多