C# 5.0将带来的五大全新功能
第一:绑定运算符,:=:
这个只是简化了数据绑定,跟ASP.NET MVC3不断改进一样,其实不是什么亮点改进。
第二:带参数的泛型构造函数:
这个的加入给一些设计增加了强大功能,泛型早在C#2.0加入后就有着强大的应用,一般稍微设计比较好的框架,都会用到泛型,C#5.0加入带参数泛型构造函数,则在原有基础上对C#泛型完善了很多。:)
//we might have
public class T MyClass : T:class, new(int)
第三:支持null类型运算:
此功能,个人觉得并非什么大的亮点,但至少对null类型,特别是有数据计算的这种null类型的支持,写代码还是方便不少。
注意对于Nullable Types,在C#2.0就加入进来了,但是不支持计算,比如:
int? y = x +40;
那么y值是多少?不支持计算,得到的是null,想必大家知道为什么结果是null了吧?但C#5.0可以,40加一个null的整数,我们要的结果是40,不过份吧?
int y? = x +40;
Myobject obj =null;
Myotherobj obj2 = obj.MyProperty ??? new Myotherobj();
第四:case支持表达式:
这个是一个我很早就想如果能这样就好了,没想到在C#5.0里就加入此功能,以前case里只能写一个具体的常量,而现在可以加表达式了,灵活多了。
casestring.IsNullorEmpty(myotherobj):
//逻辑代码
case myotherobj.Trim().Lower:
//逻辑代码
}
第五:扩展属性。
我们在C#3.0里有扩展方法,那么在C#5.0里将会加入扩展属性的感念,对照扩展方法,不难理解扩展属性的概念了。以下为扩展属性的定义举例:
public static int Zivsoft_ExtensionProperty { get;set;}
C#5.0 远远不只是上面描述的5点新功能,它如同C#4.0加入dynamic概念一样,会加入异步处理概念,这个不是几行代码就能表达,而是将在设计,架构上,又会掀起一次飞跃……
1:异步编程:
异步
C# vNext为了将异步变得更为简单,引入了2个关键字,async和await,下面简单介绍下这2个关键字给我们的编程带来怎么样的改变。
以一个标准的逻辑为例:下载一个远程URI,并将内容输出在界面上,假设我们已经有了显示内容的方法:
void Display(string text) {
// 不管是怎么实现的
}
如果用标准的同步式写法,这代码相当之容易:
void ShowUriContent(string uri) {
using (WebClient client = new WebClient()) {
string text = client.DownloadString(uri);
Display(text);
}
}
当然这不是我们讨论的重点,同步方式会造成线程的阻塞,必须选择WebClient下载完成才可以继续运行,如果这个过程在UI线程上执行,则会造成UI无响应的情况。同时网络是非常不可预测的外部条件,很可能因为网络状况不好导致程序长时间没有响应,显然不是我们希望得到的结果。
所以我们又有了异步的方案,.NET中最早的异常编程模式是Begin/End模式,不过WebClient作为WebRequest的高层封装,已经把这个模式给封装了:
void DownloadUri(string uri) {
using (WebClient client = new WebClient()) {
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ShowContent);
client.DownloadStringAsync(uri);
}
}
void ShowContent(object sender, DownloadStringCompletedEventArgs e) {
Display(e.Result);
}
看看,好好的事情一变成异步,就变得麻烦无比。一个很明确逻辑的方法活生生拆成2个来处理,虽然可以用Lambda或者delegate来使代码上进行简化,但依旧无可避免一段逻辑被拆成两段的痛苦。当更多的异步操作交叉在一起的时候,无论是代码的组织还是逻辑的梳理都会变得更加麻烦。
正因为如此,C# vNext引入了关键了,从语法上对此进行了改进,当使用async和await时,我们的代码会变成这样:
void async ShowUriContent(string uri) {
using (WebClient client = new WebClient()) {
string text = await client.DownloadStringTaskAsync(uri);
Display(text);
}
}
悄悄地告诉你,我写上面这段代码的时候,是直接把同步方案的代码复制过来再稍微发了几个字符的……由此可见,在语言级别给予支持后,代码的编写将会是如何地顺畅和简便。这段代码看上去就是一段典型的同步逻辑,创建-下载-显示按部就班,唯一不同地就是在方法声明中加入了async关键字,在DownloadStringTaskAsync方法的调用时加入了await关键字。就这么神奇地,运行时变成了异步。ShowUriContent方法会在调用DownloadStringTaskAsync后退出,而下载过程会异步进行,当下载完成后,再进入Display方法的执行,期间不会阻塞线程,不会造成UI无响应的情况。
从字面上,我们可以理解为在被调用者方法中可以获得调用者的信息,这对我们开发跟踪、
调试以及诊断工具的时候特别有用。而在之前,我们可能需要在调用者方法中自己进行相关操作,
比如插入日志信息记录哪个方法执行了等。我印象很深的是,我参与的一个项目根据要求使用微软的企业库,
在调���每个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);
}
}
}
浙公网安备 33010602011771号