• VS2015预览版中的C#6.0 新功能(一)


    VS2015预览版中的C#6.0 新功能(二)

    VS2015预览版中的C#6.0 新功能(三)

    VS2015的预览版在11月12日发布了,下面让我们来看看C#都提供了哪些新的功能。

    字符串添写(String interpolation)
          在格式化字符串时,string.Format是经常被用到的,它确实很方便使用,但是这种使用占位符,然后通过参数替换的方式还不够方便, 在C#6.0里,String interpolation语法的引入提供了另一种格式化字符串的方式。请看下面的例子:
    假设我们现在有个如下所示的Book类,现在需要格式化它的字段以输出关于该book的描述。

    public class Book
    {
          public int Number { get; set; }
    
          public string Name { get; set; }
    
          public string Abstract { get; set; }
    
          public float Price { get; set; }
    
          public List<Author> Authors { get; set; }
    }

    使用string.Format的代码如下:

    var introUsingStringFormat = string.Format("[{0}]' price is {1:F3}, its description is {2}.", book.Name, book.Price, book.Abstract);

    使用string interpolation的代码如下:

    var introUsingStrInterPolation = "[{book.Name}]' price is {book.Price : F3}, its description is {book.Abstract}.";

    完整的程序如下:

    public void Show()
    {
         //interpolate string
         var book = new Book
         {
             Abstract = "Book about C#6.0",
             Name = "C#6.0 new feature",
             Price = 10.8709f,
         };
    
         var introUsingStrInterPolation = "[{book.Name}]' price is {book.Price : F3}, its description is {book.Abstract}.";
         var introUsingStringFormat = string.Format("[{0}]' price is {1:F3}, its description is {2}.", book.Name, book.Price, book.Abstract);
         Console.WriteLine("format string using string interpolation:");
         Console.WriteLine(introUsingStrInterPolation);
         Console.WriteLine("===============================================================================");
         Console.WriteLine("format string using string.Format method:");
         Console.WriteLine(introUsingStringFormat);
         Console.Read();
    }

     如下图,两种方式的输出是一样的:

     

    总结:

    String Interpolation语法允许你在字符串里直接插入代码并可以像string.Format 那样指定format Specifier和对齐,如上面的例子{book.Price : F3}指定price的精度为3。这个语法在之后版本中会变得更加简洁,可能会采用如下的格式:

    var introUsingStrInterPolation = $"[{book.Name}]' price is {book.Price : F3}, its description is {book.Abstract}.";

    空条件运算符?

    如下面例子所示, 在程序中经常会出现对表达式中对象是否为空的连续检测。

     if (book != null && book.Authors != null)
     {
         var countOfAuthers = book.Authors.Count;
     }

     空条件运算符?使得这种检测更加方便,表达更加简洁,其使用方法如下:

    var countOfAuthersUsingNullConditional = book?.Authors?.Count;

     空条件运算符?用在成员运算符.和索引前面,会执行下面的操作:
     如果其前面的对象为空,那么直接返回null,否则允许访问前面对象的成员或者元素以继续后面运算,所以上面的表达式和下面的代码段是等价的

     if (book == null)
     {
          countOfAuthorsUsingNullConditional = null;
     }
     else if (book.Authors == null)
     {
          countOfAuthorsUsingNullConditional = null;
     }
     else
     {
          countOfAuthorsUsingNullConditional = book.Authors.Count;
     }

     上面的code展示了其执行的逻辑顺序,达到相同结果的简洁写法如下:

    if(book == null || book.Authors == null)
    {
        countOfAuthorsUsingNullConditional = null;
    }
    else         
    {            
        countOfAuthorsUsingNullConditional = book.Authors.Count;
    }

     从上可以看出其具有如下特性:

    1.  包含?的表达式返回的是引用类型
    2.  ?具有类似逻辑运算符||和&&的短路逻辑
    3.  ?自己可以组成链,正如上面例子所示的,在同一表达式中连续使用?

     此外,空条件运算符还具有如下特点:

    1.  对其前面的对象是否为空只进行一次计算
    2.  可以与合并运算符??一起使用更加方便
    3.  ?后面不能直接跟随使用()的方法调用,对于event或者delegate可以使用?.Invoke的方式来使用,由于?只计算其右边部分一次并把其保存到临时变量中,所以它是线程安全的

    下面来看一些针对2和3的例子:

    //using with coalescing operator ??
    int numberOfAuthors = book?.Authors?.Count ?? 0;
    
    //using with delegate.
    action?.Invoke();

    完整的程序如下:

    public void Show()
    {
         //traditional way
         if (book != null && book.Authors != null)
         {
               var countOfAuthors = book.Authors.Count;
               Console.WriteLine("===================using tranditional way==============");
               Console.WriteLine(countOfAuthors);
         }
    
         //the way of using null-conditional operator.
         var countOfAuthorsUsingNullConditional = book?.Authors?.Count;
         Console.WriteLine("===================null-conditional operator==============");
         Console.WriteLine(countOfAuthorsUsingNullConditional);
         Console.Read();
    
         //the logic of the expression.
         if (book == null)
         {
             countOfAuthorsUsingNullConditional = null;
         }
         else if (book.Authors == null)
         {
             countOfAuthorsUsingNullConditional = null;
         }
         else
         {
             countOfAuthorsUsingNullConditional = book.Authors.Count;
         }
               //the concise edition using tranditional way.
         if (book == null || book.Authors == null)
         {
             countOfAuthorsUsingNullConditional = null;
         }
         else
         {
             countOfAuthorsUsingNullConditional = book.Authors.Count;
         }
               //using with coalescing operator ??
         int numberOfAuthors = book?.Authors?.Count ?? 0;
    
         //using with delegate.
         action?.Invoke();
     }

    nameof表达式

    有时候我们需要获得代码中某些symbol的名字,例如在throw ArgumentNullException时,需要获得为null参数的名字(字符串形式),在调用PropertyChanged时,我们也需要获得属性的名字,直接使用字符串具有如下的缺点:

    1. 容易拼写错误
    2. 无法重构
    3. 没有语法检查

    nameof表达式能够以字符串的形式返回参数对象或者类成员的名字,下面是一些例子

     var nameOfClassPropertyObject = nameof(book);
     var nameOfArgument = nameof(author);
     var classMethodMember = nameof(Book.Equals);
     var classPropertyMember = nameof(Book.Number);
     var @class =  nameof(Book);

    从上面的例子中可以看出nameof运算符可以用于类(包括attribute类),类的成员,对象上,另外需要注意的是它只会输出最终元素的名字不会包含其前缀,例如nameof(Book.Equals)的输出是Equals。

  • 相关阅读:
    【BZOJ 3309】DZY Loves Math
    【51Nod 1239】欧拉函数之和
    【51Nod 1244】莫比乌斯函数之和
    莫比乌斯反演与杜教筛
    【BZOJ 3993】【SDOI 2015】星际战争
    【BZOJ 3876】【AHOI 2014】支线剧情
    【hihoCoder 1454】【hiho挑战赛25】【坑】Rikka with Tree II
    【BZOJ 1061】【Vijos 1825】【NOI 2008】志愿者招募
    【BZOJ 1016】【JSOI 2008】最小生成树计数
    【BZOJ 1005】【HNOI 2008】明明的烦恼
  • 原文地址:https://www.cnblogs.com/dereklovecc/p/4104357.html
Copyright © 2020-2023  润新知