• C# 5.0中新增特性


    C# 5.0随着VisualStudio 2012一起正式发布了,让我们来看看C#5.0中增加了哪些功能。

    1. 异步编程

    在.Net 4.5中,通过asyncawait两个关键字,引入了一种新的基于任务的异步编程模型(TAP)。在这种方式下,可以通过类似同步方式编写异步代码,极大简化了异步编程模型。如下式一个简单的实例:

        static async void DownloadStringAsync2(Uri uri)
        {
            var webClient = new WebClient();
            var result = await webClient.DownloadStringTaskAsync(uri);
            Console.WriteLine(result);
        }

    而之前的方式是这样的:

        static void DownloadStringAsync(Uri uri)
        {
            var webClient = new WebClient();
            webClient.DownloadStringCompleted += (s, e) =>
                {
                    Console.WriteLine(e.Result);
                };
            webClient.DownloadStringAsync(uri);
        }

    也许前面这个例子不足以体现asyncawait带来的优越性,下面这个例子就明显多了:

        public void CopyToAsyncTheHardWay(Stream source, Stream destination)
        {
            byte[] buffer = new byte[0x1000];
            Action<IAsyncResult> readWriteLoop = null;
            readWriteLoop = iar =>
            {
                for (bool isRead = (iar == null); ; isRead = !isRead)
                {
                    switch (isRead)
                    {
                        case true:
                            iar = source.BeginRead(buffer, 0, buffer.Length,
                                readResult =>
                                {
                                    if (readResult.CompletedSynchronously) return;
                                    readWriteLoop(readResult);
                                }, null);
                            if (!iar.CompletedSynchronously) return;
                            break;
                        case false:
                            int numRead = source.EndRead(iar);
                            if (numRead == 0)
                            {
                                return;
                            }
                            iar = destination.BeginWrite(buffer, 0, numRead,
                                writeResult =>
                                {
                                    if (writeResult.CompletedSynchronously) return;
                                    destination.EndWrite(writeResult);
                                    readWriteLoop(null);
                                }, null);
                            if (!iar.CompletedSynchronously) return;
                            destination.EndWrite(iar);
                            break;
                    }
                }
            };
            readWriteLoop(null);
        }

        public async Task CopyToAsync(Stream source, Stream destination)
        {
            byte[] buffer = new byte[0x1000];
            int numRead;
            while ((numRead = await source.ReadAsync(buffer, 0, buffer.Length)) != 0)
            {
                await destination.WriteAsync(buffer, 0, numRead);
            }
        }

    关于基于任务的异步编程模型需要介绍的地方还比较多,不是一两句能说完的,有空的话后面再专门写篇文章来详细介绍下。另外也可参看微软的官方网站:Visual Studio Asynchronous Programming,其官方文档Task-Based Asynchronous Pattern Overview介绍的非常详细, VisualStudio中自带的CSharp Language Specification中也有一些说明。

    2. 调用方信息

    很多时候,我们需要在运行过程中记录一些调测的日志信息,如下所示:

        public void DoProcessing()
        {
            TraceMessage("Something happened.");
        }

    为了调测方便,除了事件信息外,我们往往还需要知道发生该事件的代码位置以及调用栈信息。在C++中,我们可以通过定义一个宏,然后再宏中通过__FILE__和__LINE__来获取当前代码的位置,但C#并不支持宏,往往只能通过StackTrace来实现这一功能,但StackTrace却有不是很靠谱,常常获取不了我们所要的结果。

    针对这个问题,在.Net 4.5中引入了三个Attribute:CallerMemberNameCallerFilePathCallerLineNumber。在编译器的配合下,分别可以获取到调用函数(准确讲应该是成员)名称,调用文件及调用行号。上面的TraceMessage函数可以实现如下:

        public void TraceMessage(string message,
                [CallerMemberName] string memberName = "",
                [CallerFilePath] string sourceFilePath = "",
                [CallerLineNumber] int sourceLineNumber = 0)
        {
            Trace.WriteLine("message: " + message);
            Trace.WriteLine("member name: " + memberName);
            Trace.WriteLine("source file path: " + sourceFilePath);
            Trace.WriteLine("source line number: " + sourceLineNumber);
        }

    另外,在构造函数,析构函数、属性等特殊的地方调用CallerMemberName属性所标记的函数时,获取的值有所不同,其取值如下表所示:

    调用的地方

    CallerMemberName获取的结果

    方法、属性或事件

    方法,属性或事件的名称

    构造函数

    字符串 ".ctor"

    静态构造函数

    字符串 ".cctor"

    析构函数

    该字符串 "Finalize"

    用户定义的运算符或转换

    生成的名称成员,例如, "op_Addition"。

    特性构造函数

    特性所应用的成员的名称

    例如,对于在属性中调用CallerMemberName所标记的函数即可获取属性名称,通过这种方式可以简化 INotifyPropertyChanged 接口的实现。关于调用方信息更详细的资料,请参看MSDN:http://msdn.microsoft.com/zh-cn/library/hh534540.aspx

  • 相关阅读:
    Uploadify跨域上传原理
    C#中HttpClient使用注意:预热与长连接
    前端必读:浏览器内部工作原理
    从零开始学习jQuery
    ManualResetEvent 类的用法
    线程池用法的改进
    我的第一篇博客
    Es6新语法 let篇
    如何测试解析是否生效?
    主机记录和记录值(域名服务器绑定详解)
  • 原文地址:https://www.cnblogs.com/TianFang/p/2646146.html
Copyright © 2020-2023  润新知