C#进化图
C#如今已经发展到5.0版本,CLR版本为4.5,伴随Visual Studio 2011发布。我总结了一个进化图,以供大家参考。
在C# 5.0中主要增加了Async Programming 以及Caller Information两个特性,以下分别作介绍。
Async Feature
在C# 5.0新增了async修饰符以及await操作符;标记有async的方法被称为异步方法。
异步编程可以给我们带来很大的便利。比如在WinForm编程中,当我们使用HttpWebRequest请求网络资源的时候,
如果使用同步请求,那么如果请求响应时间过长,会导致我们的UI线程堵塞,
从直观上的感受是窗体无响应或者无法进行UI交互操作。
private void btnTest_Click(object sender, EventArgs e)
{
var request = WebRequest.Create(txtUrl.Text.Trim());
var content=new MemoryStream();
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
responseStream.CopyTo(content);
}
}
txtResult.Text = content.Length.ToString();
}
当点击Test按钮后,在txtResult显示结果之前,我们将不能对窗体进行任何操作。
在没有async之前,我们一般也可以使用BeginGetResponse方法进行异步操作,如MSDN文档上的示例所示,
我们需要编写大量的代码去实现异步的效果:
https://msdn.microsoft.com/zh-cn/library/system.net.httpwebrequest.begingetresponse(v=vs.80).aspx。
下面我们将对以上的窗体进行改造,使用新增的异步编程特性,代码如下:
private async void btnTest_Click(object sender, EventArgs e)
{
var request = WebRequest.Create(txtUrl.Text.Trim());
var content = new MemoryStream();
Task<WebResponse> responseTask = request.GetResponseAsync();
using (var response = await responseTask)
{
using (var responseStream = response.GetResponseStream())
{
Task copyTask = responseStream.CopyToAsync(content);
//await operator to supends the excution of the method until the task is
completed. In the meantime, the control is returned the UI thread.
await copyTask;
}
}
txtResult.Text = content.Length.ToString();
}
通过await,可以使我们在语义上让我们理解为reponse为异步执行后的结果,而编译器会负责所有的代码生成,
我们无需再去操作复杂的Callback。这样为我们异步编程节省很多的时间。从直观上,当我们使用以上代码后,
窗体在点击Test按钮后,我们还可以进行交互操作。
Caller Information
从字面上,我们可以理解为在被调用者方法中可以获得调用者的信息,这对我们开发跟踪、
调试以及诊断工具的时候特别有用。而在之前,我们可能需要在调用者方法中自己进行相关操作,
比如插入日志信息记录哪个方法执行了等。我印象很深的是,我参与的一个项目根据要求使用微软的企业库,
在调用每个Data Access的方法前都要插入调用者的信息到日志中,以便跟踪调查等;
这样导致每个调用者方法都会有相同的调用记录日志的方法的代码。有了Caller Information,
我们可以在被调用者方法中获得以下几个信息:
CallerFilePathAttribute 调用者方法所在的源文件地址
CallerLineNumberAttribute 方法被调用的行号
CallerMemberNameAttribute 调用方法的名称
下面我将举例说明。
在以前我们可能会用到如下的方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplicationTest
{
class Program
{
static void Main(string[] args)
{
InsertLog("Main");
MethodB();
Console.ReadLine();
}
static void MethodA()
{
InsertLog("MethodA");
MethodB();
}
static void MethodB()
{ }
static void InsertLog(string methodName)
{
Console.WriteLine("{0} called method B at {1}", methodName,
DateTime.Now);
}
}
}
在Main和MethodA中都调用了InsertLog方法。有了新特性的支持,我们可以修改代码为:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplicationTest
{
class Program
{
static void Main(string[] args)
{
//InsertLog("Main");
MethodB();
Console.ReadLine();
}
static void MethodA()
{
//InsertLog("MethodA");
MethodB();
}
static void MethodB(
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
InsertLog(memberName);
}
static void InsertLog(string methodName)
{
Console.WriteLine("{0} called method B at {1}", methodName,
DateTime.Now);
}
}
}
总结
C# 5.0新增的特性可以提高我们编程的效率同时减少代码量,VS11 IDE方面也新增加了很多新的功能,
大家可以慢慢去体会。
Author's Bio
MVP Mondays The MVP Monday Series is created by Melissa Travers. In this series we work to provide readers with a guest post from an MVP every Monday. Melissa is a Community Program Manager for Dynamics, Excel, Office 365, Platforms and SharePoint in the United States. She has been working with MVPs since her early days as Microsoft Exchange Support Engineer when MVPs would answer all the questions in the old newsgroups before she could get to them. |