zoukankan      html  css  js  c++  java
  • C# 5.0新加特性

    1. 异步编程

    在.Net 4.5中,通过async和await两个关键字,引入了一种新的基于任务的异步编程模型(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);
        }

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

        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:CallerMemberName、CallerFilePath和CallerLineNumber。在编译器的配合下,分别可以获取到调用函数(准确讲应该是成员)名称,调用文件及调用行号。上面的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 接口的实现。

  • 相关阅读:
    poj 3321 Apple Tree
    hdu 1520 Anniversary party
    Light OJ 1089 Points in Segments (II)
    Timus 1018 Binary Apple Tree
    zoj 3299 Fall the Brick
    HFUT 1287 法默尔的农场
    Codeforces 159C String Manipulation 1.0
    GraphQL + React Apollo + React Hook 大型项目实战(32 个视频)
    使用 TypeScript & mocha & chai 写测试代码实战(17 个视频)
    GraphQL + React Apollo + React Hook + Express + Mongodb 大型前后端分离项目实战之后端(19 个视频)
  • 原文地址:https://www.cnblogs.com/kylin2016/p/5817088.html
Copyright © 2011-2022 走看看