C#高级编程9 第17章 使用VS2013-C#特性

本文深入介绍了C#6.0与C#7.0的重要新特性,包括NameOf表达式、空值判断操作符、字符串嵌入值等C#6.0特性,以及out变量、元组、匹配模式等C#7.0特性,旨在帮助开发者掌握这些新特性的使用方法。

C#高级编程9 第17章 使用VS2013

编辑定位到

 

如果默认勾选了这项,请去掉勾选,因为勾选之后解决方案的目录会根据当前文件选中。

 可以设置项目并行生成数

 

版本控制软件设置

所有文本编辑器行号显示

 

启用编辑继续

 收集调试信息,将影响性能

 

 Code Compare这是扩展与更新里面的插件,安装之后才会显示,用来比较代码是否相同

 nuget包源配置,提供了nuget更新的数据源

 目标框架的设置影响到项目基础框架的引用,不同目标框架的项目之间不能互相引用。

 不安全代码和警告等级可能会影响生成

特定页指定了项目运行的起始页面,URL指定了端口号和虚拟目录,必须创建虚拟目录之后才能运行项目,调试器一般使用asp.net

 项目发布一般只需要运行所需的文件

 windows服务项目可以选择启用本机调试,如果出现无法写入内存的错误时。

web发布

 

 

 

 

 

 

 

VS2015....VS2017...

 

C#6.0特性:

    1. NameOf表达式。曾几何时,我们一直在hardcode各种参数异常,譬如: 
      void ThrowArgumentNullException(string firstVersionArgumentName) 

        threw new ArgumentNullException(“firstVersionArgumentName”, “can not be null”); 

      很悲催的是第二版说不定PM就说:“这个参数名字不合适,咱改改吧”,得益于IDE的重构功能,这个很容易,直接F2改名然后回车,签入代码;若干天后,测试找上门来,说你的参数名字是变了,但是异常信息没变。好吧,原来这里的hardcode字符组,这个是不会随着重构功能改变的! 
      再来看看新的Nameof表达式给我带来什么,同样的功能,代码如下: 
      void ThrowArgumentNullException(string firstVersionArgumentName) 

        threw new ArgumentNullException(nameof(firstVersionArgumentName), “can not be null”); 

      在回到IDE中,再次按F2触发重构改名,你会发现异常信息也能一起改变了。
    2. 空值判断操作符(Null-conditional operators),又一个重量级代码提升,直接上示例代码: 
      public static string Tuncate(this string value, int length) 

        if(!string.IsNullOrEmpty(value)) 
        { 
          return value.Substring(0, Math.Min(value.Length, length)); 
        } 
        return value; 

      这只是一个很小的折影,在开发过程中我们有无数这样的方法,无数次重复为空判断,但是这对代码的可读性和业务处理没有任何提升,反而增加了代码复杂度,让我们更难理解当初的设计初衷。显然,C#6.0使用null-conditional operators来向前推进了一大步: 
      public static string Tuncate(this string value, int length) 

        return value?.Substring(0, Math.Min(value.Length, length)); 

      是不是更加简洁明了,而且能突出业务核心逻辑!
    3. 字符串嵌入值(string interpolation),终于可以摆脱长长的string.Format函数了,如下代码就可以轻松改写了: 
      var fullName = string.Format(“FirstName is {0}, LastName is {1}”, customer.FirstName, customer.LastName); 
      使用新特性之后代码: 
      var fullName = “FirstName is \{customer.FirstName}, LastName is \{customer.LastName}”;
    4. Lambda表达式函数和仅get的属性。对于那些只有一两句话的函数,可以省掉一些废话了,这个新功能可以大大节省人力: 
      public override string ToString() => “\{FirstName} \{LastName}”; 
      public override int GetHashcode() => (FirstName.GetHashcode()^8) & (LastName.GetHashcode()); 
      public DateTime TimeStamp { get; } => DateTime.UtcNow;
    5. 自动属性(auto-property)和索引初始化(Index initializers),终于可以像变量一样给属性赋初值了,大大提升代码可读性。 
      public string FirstName { get; set; } = “John”; 
      public string LastName { get; set; } = “Lennon”; 
      private Dictionary<int, string> _dicts = new Dictionary<int, string> { [3] = “third”, [8] = “eight” }; 
      public string FullName { get; } 
      pubic MyClass ()  

        FullName = “\{FirstName} \{LastName}”; 
      }
    6. 异常过滤器(Exception filter),回想曾经的错误处理,为了提示不同的错误,我们不得不定义多个自定义异常,有了异常过滤器之后,我们可以通过给异常添加一个简单的额外属性就可以解决了: 
      try { … } 
      catach ( CustomException ex ) if ( CheckException(ex) ) 
      { … }  
      想想这个还有一个好处,比如严重异常日志,在这个过滤器里我们可以最简单的判断,发现若果是严重的问题,可以直接做更早的提醒。
    7. 引用静态类(using static),懒人必备,想想某大仙在前面定义了一个超级无敌的静态类和辅助方法,你有超级多的地方需要用,然后你就得一遍一遍的敲这个静态类名和方法名,万一这个静态类名字很长就更悲催了,拷贝吧,最后总是看着大段大段重复心里很不爽(程序员大部分都有代码洁癖),好吧,这个应用静态类就能很好的解决了: 
      using GrapeCity.Demo.LongLongNameStaticClass; 
      void AnotherMethod() 

        UtilA(…) // no LongLongNameStaticClass.UtilA(…) 
      }
    8. Await增强,终于可以把await放到catch和finally块中了,典型的用例是像IO资源操作之类可以简单整洁的处理关闭了: 
      Resource res = null; 
      try 

        res = await Resource.OpenAsync(…); //一直都可以而且一直这么做的 
        ... 

      catch(ResourceException ex) 

        await Resource.LogAsync(res, ex); //写日志吧,不阻塞 

      finally 

        res?.CloseAsync(); //结合空值判断操作符更简洁明了 
      }

C#7.0特性

    

1. out-variables(Out变量)

以前,我们使用out变量的时候,需要在外部先申明,然后才能传入方法,类似如下:

string ddd = ""; //先申明变量
ccc.StringOut(out ddd);
Console.WriteLine(ddd);

c#7.0中我们可以不必申明,直接在参数传递的同时申明它,如下:

 StringOut(out string ddd); //传递的同时申明
Console.WriteLine(ddd);
Console.ReadLine();

 

2.Tuples(元组)

曾今在.NET4.0中,微软对多个返回值给了我们一个解决方案叫元组,类似代码如下:

 static void Main(string[] args)
 {
            var data = GetFullName();
            Console.WriteLine(data.Item1);
            Console.WriteLine(data.Item2);
            Console.WriteLine(data.Item3);
            Console.ReadLine();
}
static Tuple<string, string, string> GetFullName() 
{
           return  new Tuple<string, string, string>("a", "b", "c");
}

上面代码展示了一个方法,返回含有3个字符串的元组,然而当我们获取到值,使用的时候 心已经炸了,Item1,Item2,Item3是什么鬼,虽然达到了我们的要求,但是实在不优雅

那么,在C#7.0中,微软提供了更优雅的方案:(注意:需要通过nuget引用System.ValueTuple)如下:

        static void Main(string[] args)
        {
            var data=GetFullName();
            Console.WriteLine(data.a); //可用命名获取到值
            Console.WriteLine(data.b);
            Console.WriteLine(data.c);
            Console.ReadLine();

        }


        //方法定义为多个返回值,并命名
        private static (string a,string b,string c) GetFullName()
        {
            return ("a","b","c");
        }

解构元组,有的时候我们不想用var匿名来获取,那么如何获取abc呢?我们可以如下:

 static void Main(string[] args)
        {
           //定义解构元组
            (string a, string b, string c) = GetFullName();

            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
            Console.ReadLine();

        }

        private static (string a,string b,string c) GetFullName()
        {
            return ("a","b","c");
        }

 

3. Pattern Matching(匹配模式)

在C#7.0中,引入了匹配模式的玩法,先举个老栗子.一个object类型,我们想判断他是否为int如果是int我们就加10,然后输出,需要如下:

object a = 1;
if (a is int) //is判断
{
  int b = (int)a; //拆
  int d = b+10; //加10
  Console.WriteLine(d); //输出
}

那么在C#7.0中,首先就是对is的一个小扩展,我们只需要这样写就行了,如下:

object a = 1;
if (a is int c) //这里,判断为int后就直接赋值给c
{
  int d = c + 10;
  Console.WriteLine(d);
}

这样是不是很方便?特别是经常用反射的同志们..

那么问题来了,挖掘机技术哪家强?!(咳咳,呸 开玩笑)

其实是,如果有多种类型需要匹配,那怎么办?多个if else?当然没问题,不过,微软爸爸也提供了switch的新玩法,我们来看看,如下:

我们定义一个Add的方法,以Object作为参数,返回动态类型

        static dynamic Add(object a)
        {
            dynamic data;
            switch (a)
            {
                case int b:
                    data=b++;
                    break;
                case string c:
                    data= c + "aaa";
                    break;
                default:
                    data = null;
                    break;
            }
            return data;
        }

下面运行,传入int类型:

object a = 1;
var data= Add(a);
Console.WriteLine(data.GetType());
Console.WriteLine(data);

输出如图:

我们传入String类型的参数,代码和输出如下:

object a = "bbbb";
var data= Add(a);
Console.WriteLine(data.GetType());
Console.WriteLine(data);

通过如上代码,我们就可以体会到switch的新玩法是多么的顺畅和强大了.

匹配模式的Case When筛选

有的基友就要问了.既然我们可以在Switch里面匹配类型了,那我们能不能顺便筛选一下值?答案当然是肯定的.

我们把上面的Switch代码改一下,如下:

            switch (a)
            {
                case int b when b < 0:
                    data = b + 100;
                    break;
                case int b:
                    data=b++;
                    break;
                case string c:
                    data= c + "aaa";
                    break;
                default:
                    data = null;
                    break;
            }

在传入-1试试,看结果如下:

 

 

4.ref locals and returns(局部变量和引用返回)

 

首先我们知道 ref关键字是将值传递变为引用传递

那么我们先来看看ref locals(ref局部变量)

列子代码如下:

       static  void Main(string[] args)
        {

            int x = 3;
            ref int x1 = ref x;  //注意这里,我们通过ref关键字 把x赋给了x1
            x1 = 2;
            Console.WriteLine($"改变后的变量 {nameof(x)} 值为: {x}");
            Console.ReadLine();

        }

这段代码最终输出 "2"

大家注意注释的部分,我们通过ref关键字把x赋给了x1,如果是值类型的传递,那么对x将毫无影响 还是输出3.

好处不言而喻,在某些特定的场合,我们可以直接用ref来引用传递,减少了值传递所需要开辟的空间.

 

接下来我们看看ref  returns (ref引用返回)

这个功能其实是非常有用的,我们可以把值类型当作引用类型来进行return

老规矩,我们举个栗子,代码如下:

很简单的逻辑..获取指定数组的指定下标的值

static ref int GetByIndex(int[] arr, int ix) => ref arr[ix];  //获取指定数组的指定下标

我们编写测试代码如下:

            int[] arr = { 1, 2, 3, 4, 5 };
            ref int x = ref GetByIndex(arr, 2); //调用刚才的方法
            x = 99;
            Console.WriteLine($"数组arr[2]的值为: {arr[2]}");
            Console.ReadLine();

我们通过ref返回引用类型,在重新赋值, arr数组中的值,相应也改变了.

总结一下:ref关键字很早就存在了,但是他只能用于参数,这次C#7.0让他不仅仅只能作为参数传递,还能作为本地变量和返回值了

 

5.Local Functions (局部函数)

嗯,这个就有点颠覆..大家都知道,局部变量是指:只在特定过程或函数中可以访问的变量。

那这个局部函数,顾名思义:只在特定的函数中可以访问的函数(妈蛋 好绕口)

使用方法如下:

 

       public static void DoSomeing()
        {
            //调用Dosmeing2
            int data = Dosmeing2(100, 200);
            Console.WriteLine(data);
            //定义局部函数,Dosmeing2.
            int Dosmeing2(int a, int b)
            {
               return a + b;
            }
        }

呃,解释下来 大概就是在DoSomeing中定义了一个DoSomeing2的方法,..在前面调用了一下.(注:值得一提的是局部函数定义在方法的任何位置,都可以在方法内被调用,不用遵循逐行解析的方式)

 

6.More expression-bodied members(更多的函数成员的表达式体)

C#6.0中,提供了对于只有一条语句的方法体可以简写成表达式。

如下:

        public void CreateCaCheContext() => new CaCheContext();
        //等价于下面的代码
        public void CreateCaCheContext()
        {
            new CaCheContext();
        } 

但是,并不支持用于构造函数,析构函数,和属性访问器,那么C#7.0就支持了..代码如下:

// 构造函数的表达式写法
public CaCheContext(string label) => this.Label = label;

// 析构函数的表达式写法
~CaCheContext() => Console.Error.WriteLine("Finalized!");

private string label;

// Get/Set属性访问器的表达式写法
public string Label
{
    get => label;
    set => this.label = value ?? "Default label";
}

7.throw Expressions (异常表达式)

在C#7.0以前,我们想判断一个字符串是否为null,如果为null则抛除异常,我们需要这么写:

        public string IsNull()
        {
            string a = null;
            if (a == null)
            {
                throw new Exception("异常了!");
            }
            return a;
        }

 

这样,我们就很不方便,特别是在三元表达式 或者非空表达式中,都无法抛除这个异常,需要写if语句.

那么我们在C#7.0中,可以这样:

        public string IsNull()
        {
            string a = null;
            return a ?? throw new Exception("异常了!");
        }

 

8.Generalized async return types (通用异步返回类型)

嗯,这个,怎么说呢,其实我异步用的较少,所以对这个感觉理解不深刻,还是觉得然并卵,在某些特定的情况下应该是有用的.

我就直接翻译官方的原文了,实例代码也是官方的原文.

异步方法必须返回 void,Task 或 Task<T>,这次加入了新的ValueTask<T>,来防止异步运行的结果在等待时已可用的情境下,对 Task<T> 进行分配。对于许多示例中设计缓冲的异步场景,这可以大大减少分配的数量并显著地提升性能。

官方的实例展示的主要是意思是:一个数据,在已经缓存的情况下,可以使用ValueTask来返回异步或者同步2种方案

    public class CaCheContext
    {
        public ValueTask<int> CachedFunc()
        {
            return (cache) ? new ValueTask<int>(cacheResult) : new ValueTask<int>(loadCache());
        }
        private bool cache = false;
        private int cacheResult;
        private async Task<int> loadCache()
        {
            // simulate async work:
            await Task.Delay(5000);
            cache = true;
            cacheResult = 100;
            return cacheResult;
        }
    }

调用的代码和结果如下:

        //main方法可不能用async修饰,所以用了委托.
        static  void Main(string[] args)
        {
            Action act = async () =>
            {
                CaCheContext cc = new CaCheContext();
                int data = await cc.CachedFunc();
                Console.WriteLine(data);
                int data2 = await cc.CachedFunc();
                Console.WriteLine(data2);
            };
            // 调用委托  
            act();
            Console.Read();

        }

上面的代码,我们连续调用了2次,第一次,等待了5秒出现结果.第二次则没有等待直接出现结果和预期的效果一致.

 

9.Numeric literal syntax improvements(数值文字语法改进)

这个就纯粹的是..为了好看了.

在C#7.0中,允许数字中出现"_"这个分割符号.来提高可读性,举例如下:

            int a = 123_456;
            int b = 0xAB_CD_EF;
            int c = 123456;
            int d = 0xABCDEF;
            Console.WriteLine(a==c);
            Console.WriteLine(b==d);
            //如上代码会显示两个true,在数字中用"_"分隔符不会影响结果,只是为了提高可读性
   

当然,既然是数字类型的分隔符,那么 decimalfloat 和 double  都是可以这样被分割的..

转载于:https://www.cnblogs.com/licin/p/7235007.html

☆ 资源说明:☆ [Wrox] Visual Studio 2013 高级编程 (英文版) [Wrox] Professional Visual Studio 2013 (E-Book) ☆ 图书概要:☆ Comprehensive guide to Visual Studio 2013 Visual Studio is your essential tool for Windows programming. Visual Studio 2013 features important updates to the user interface and to productivity. In Professional Visual Studio 2013, author, Microsoft Certified Trainer, and Microsoft Visual C# MVP Bruce Johnson brings three decades of industry experience to guide you through the update, and he doesn&#39;t just gloss over the basics. With his unique IDE-centric approach, he steers into the nooks and crannies to help you use Visual Studio 2013 to its maximum potential. - Choose from more theme options, check out the new icons, and make your settings portable - Step up your workflow with hover colors, auto brace completion, peek, and CodeLens - Code ASP.NET faster than ever with new shortcuts - Get acquainted with the new SharePoint 2013 environment - Find your way around the new XAML editor for Windows Store apps Visual Studio 2013 includes better support for advanced debugging techniques, vast improvements to the visual database tools, and new support for UI testing for Windows Store apps. This update is the key to smoother, quicker programming, and Professional Visual Studio 2013 is your map to everything inside. ☆ 出版信息:☆ [作者信息] Bruce Johnson [出版机构] Wrox [出版日期] 2014年03月17日 [图书页数] 1104页 [图书语言] 英语 [图书格式] PDF 格式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值