原文地址:http://www.codeproject.com/Tips/1023426/Whats-New-in-Csharp

本来想翻译一下贴出来,但是好像很多语言组织起来比较困难,读书少不会表达了。

最近一直强迫自己都一些英文资料努力提交英文阅读水平。

从c#6发布有段时间了,一个片段一个片段的看到说c#6的新特性,感觉都不是很全,总感觉老外貌似有好多时间去整理,而且整理的很详细。

C# 6.0. features walkthrough with easy to understand examples.

Introduction

Get a quick glance at what's new in C# 6.0. Features walkthrough with easy to understand examples.

What's New in C# 6.0

Static Types as using

So, we are all quite familiar with this notion of accessing static class members using the qualification first. It is not required now. Importing static using can save the day. For example, before C# 6.0, we had to accessReadKey(), WriteLine() methods of the Console class by explicitly defining the static class qualifier.

using System;namespace NewInCSharp
{class Program{static void Main(string[] args){MySelf.WhoAmI();Console.ReadKey();}}static class MySelf{public static void WhoAmI(){Console.WriteLine("I'm Fizz!");}}
}
 

In C# 6.0, we can get rid of the qualifiers just by importing the static types in the namespace like below:

using static System.Console;
using static NewInCSharp.MySelf;    /* Magic happens here */namespace NewInCSharp
{class Program{static void Main(string[] args){WhoAmI();ReadKey();}}static class MySelf{public static void WhoAmI(){WriteLine("I'm Fizz!");}}
}
String Interpolation

You can now forget using placeholders in strings to replace them with real values. C# 6 has a new feature called string interpolation using which you can now directly write your arguments instead of referring them with placeholders inside a string. You can also do whatever you would have done previously withString.Format() function.

Before C# 6.0
using System;
using System.Collections.Generic;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){string name = "Murphy Cooper";string planet = "Cooper Station";WriteLine("{0} is actually named after {1}", planet, name);ReadLine();}}
}
After C# 6.0
using System;
using System.Collections.Generic;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){string name = "Murphy Cooper";string planet = "Cooper Station";/* Magic happens here */WriteLine($"{planet} is actually named after {name}");ReadLine();}}
}

Again, these are a few string formatting examples which I missed in the video. [Check the video link at the bottom of the article.]

string name = "Sammy Jenkins";
double salary = 1000;WriteLine($"{name}'s monthly salary is {salary:C2}");
WriteLine($"Man! This {name} is kind of a
{(salary >= 1000 ? "rich guy" : "poor guy")}");/*Output:
    Sammy Jenkins's monthly salary is $1000.00
    Man! This Sammy Jenkins is kind of a rich guy
*/
Dictionary Initializers

C# 6.0 changed the way you can initialize Dictionary. Previously on C# 5, you would have to initialize theDictionary with this type of syntax, {"Key", "Value"}. Now in C# 6, you can just place the key between two curly brackets ["Key"] and then set the value of the key ["Key"] = "value"; , just like you set the value for other types of variable. This new syntax is friendlier than before.

Before C# 6
using System.Collections.Generic;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){Dictionary<string, string=""> alien = new Dictionary<string, string="">(){{"Name", "Fizzy"},{"Planet", "Kepler-452b"}};foreach (KeyValuePair<string, string=""> keyValuePair in alien){WriteLine(keyValuePair.Key + ": " + keyValuePair.Value + "\n");}ReadLine();}}
}
In C# 6.0
using System.Collections.Generic;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){/* The new and friendly syntax */ Dictionary<string, string=""> alien = new Dictionary<string, string="">(){["Name"] = "Fizzy",["Planet"] = "Kepler-452b"};foreach (KeyValuePair<string, string=""> keyValuePair in alien){WriteLine(keyValuePair.Key + ": " + keyValuePair.Value + "\n");}ReadLine();}}
}
Auto-Property Initializers

C# 6.0 came with a new concept of initializing class properties inline rather than initializing them within the type's constructor. Another handy technique is, if you want to make the setter of a property private to block users from setting value in the property by an instance, you can just declare a getter only property. For example:

Before C# 6
using static System.Console;namespace NewInCSharp
{class Program{static void Main(string[] args){Employee employee = new Employee();WriteLine("Name: " + employee.Name + "\nSalary: " + employee.Salary);ReadKey();}public class Employee{public string Name { get; set; } public decimal Salary { get; set; }public Employee(){/* Initializing property through constructor */Name = "Sammy Jenkins";Salary = 10000; }}}
}
 

In C# 6.0
using static System.Console;namespace NewInCSharp
{class Program{static void Main(string[] args){Employee employee = new Employee();WriteLine("Name: " + employee.Name + "\nSalary: " + employee.Salary);ReadKey();}public class Employee{/* Getter only property with inline initialization */public string Name { get; } = "Sammy Jenkins"/* Property with inline initialization */public decimal Salary { get; set; } = 10000; }}
}
nameof expression

Next one is the nameof expression. In enterprise level applications, lines of code run like a mad horse. So there is no means of avoiding exception handling where it is necessary. Showing a specific type name with an error message can be a quick way to find the code block where the exception just occurred. But we should also consider refactoring issues. We cannot just simply append a hard coded type name string with an error message and show it to the user because the type name can be changed anytime while refactoring but hard coded string won't change accordingly. So C# 6.0 introduced this concept of nameof expression. A simple example would be like this:

Before C# 6
using System;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){try{CallSomething();}catch (Exception exception){WriteLine(exception.Message);}ReadKey();}private static void CallSomething(){int? x = null;if (x == null){throw new Exception("x is null");/* x is the type name. What if someone changes the
                type name from x to i? The exception below would be inappropriate. */}}}
}
class Program
{private static void Main(string[] args){try{CallSomething();}catch (Exception exception){WriteLine(exception.Message);}ReadKey();}private static void CallSomething(){int? x = null;if (x == null){throw new Exception("x is null");}}
}
In C# 6.0
using System;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){try{CallSomething();}catch (Exception exception){WriteLine(exception.Message);}ReadKey();}private static void CallSomething(){int? number = null;if (number == null){throw new Exception(nameof(number) + " is null");}}}
}
Await in catch/finally Block

I think many of you were waiting for this feature in C# where you can write asynchronous code inside catch andfinally block. Well, now you can do that.

using System;
using System.Net.Http;
using System.Threading.Tasks;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){Task.Factory.StartNew(() => GetWeather());ReadKey();}private async static Task GetWeather(){HttpClient client = new HttpClient();try{var result = await client.GetStringAsync("http://api.openweathermap.org/data/2.5/weather?q=Dhaka,bd");WriteLine(result);}catch (Exception exception){try{/* If the first request throws an exception,
                    this request will be executed.
                        Both are asynchronous request to a weather service*/var result = await client.GetStringAsync("http://api.openweathermap.org/data/2.5/weather?q=NewYork,us");WriteLine(result);}catch (Exception){throw;}}}}
}
Null Conditional Operator & Null Propagation

Again, we have this new notion of null conditional operator where you can remove declaring a conditional branch to check to see if an instance of an object is null or not with this new ?. ?? null conditional operator syntax. The ?. is used to check if an instance is null or not, if it's not null then execute the code after ?. but if it is not, then execute code after ??. Check out the example below:

Before C# 6.0
using System;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){SuperHero hero = new SuperHero();if (hero.SuperPower == String.Empty){hero = null;}/* old syntax of checking if an instance is null or not */WriteLine(hero != null ? hero.SuperPower : "You aint a super hero.");ReadLine();}}public class SuperHero{public string SuperPower { get; set; } = "";}
}
In C# 6.0
using System;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){SuperHero hero = new SuperHero();if (hero.SuperPower == String.Empty){hero = null;}/* New null conditional operator */WriteLine(hero?.SuperPower ?? "You aint a super hero.");ReadLine();}}public class SuperHero{public string SuperPower { get; set; } = "";}
}

Again checking a list instance if it is null or not and then accessing its index is also somewhat similar.

using System;
using System.Collections.Generic;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){List<superhero> superHeroes = null;SuperHero hero = new SuperHero();if (hero.SuperPower != String.Empty){superHeroes = new List<superhero>();superHeroes.Add(hero);}WriteLine(superHeroes?[0].SuperPower ?? "There is no such thing as super heros.");ReadLine();}}public class SuperHero{public string SuperPower { get; set; } = "";}
}

What if you want to invoke an event/delegate after checking if the handler function is null or not? Well, thenull checking syntax would be like in the example below. It is also known as null propagation.

Before C# 6.0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){Movie movie = new Movie();movie.Title = "The Shawshank Redemption";movie.Rating = 9.3;WriteLine("Title: "+ movie.Title + "\nRating: " + movie.Rating);ReadLine();}}public class Movie : INotifyPropertyChanged{public string Title { get; set; }public double Rating { get; set; }public event PropertyChangedEventHandler PropertyChanged;protected void OnPropertyChanged(string name){PropertyChangedEventHandler handler = PropertyChanged;/* Old syntax of checking if a handler is null or not */if (handler != null){handler(this, new PropertyChangedEventArgs(name));}}}
}

In C# 6.0

using System;
using System.Collections.Generic;
using System.ComponentModel;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){Movie movie = new Movie();movie.Title = "The Shawshank Redemption";movie.Rating = 9.3;WriteLine("Title: "+ movie.Title + "\nRating: " + movie.Rating);ReadLine();}}public class Movie : INotifyPropertyChanged{public string Title { get; set; }public double Rating { get; set; }public event PropertyChangedEventHandler PropertyChanged;protected void OnPropertyChanged(string name){PropertyChangedEventHandler handler = PropertyChanged;/* Null propagation syntax */handler?.Invoke(this, new PropertyChangedEventArgs(name));}}
}

Expression Bodied Function & Property

You can now write functions and computed properties like lamda expressions to save extra headache of defining function and property statement block. Just use the lambda operator => and then start writing your code that goes into your function/property body. Here is a simple example:

using static System.Console;namespace NewInCSharp
{internal class Program{private static void Main(string[] args){double x = 1.618;double y = 3.142;WriteLine(AddNumbers(x, y));ReadLine();}/* Expression bodied function */private static double AddNumbers(double x, double y) => x + y;}
}

For expression bodied property:

using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){Person person = new Person();WriteLine("I'm " + person.FullName);ReadLine();}public class Person{public string FirstName { get; } = "Fiyaz";public string LastName { get; } = "Hasan";/* Expression bodied computed property */public string FullName => FirstName + " " + LastName;}}
}

Static Using with Extension Methods

This one is kind of related to the first one. Those of you who are wondering that if I import static types in my namespace, how would I deal with the extension methods. Well, extension methods are also static methods. It is true if you import a static type which has an extension method, you just cannot access the extension methods. It says, "The name [name of the function] does not exist in the current context". So what to do then? Well, you can explicitly write the static type name like in C# 5 or previous versions or you can simply execute the function on one of its accepted types. Let me make it clear by an example:

Before C# 6
using System;namespace NewInCSharp
{class Program{private static void Main(string[] args){Shape shape = new Shape();ShapeUtility.GenerateRandomSides(shape);Console.WriteLine(ShapeUtility.IsPolygon(shape));Console.ReadLine();}}public class Shape{public int Sides { get; set; }}public static class ShapeUtility{public static bool IsPolygon(this Shape shape){return shape.Sides >= 3;}public static void GenerateRandomSides(Shape shape){Random random = new Random();shape.Sides = random.Next(1, 6);}}
}

In C# 6.0, importing static types and accessing extension methods of them like the code above will give you an error. The following code will generate the "The name 'IsPolygon' does not exist in the current context".

using System;
using static System.Console;
using static NewInCSharp.ShapeUtility;namespace NewInCSharp
{class Program{private static void Main(string[] args){Shape shape = new Shape();GenerateRandomSides(shape);WriteLine(IsPolygon(shape));ReadLine();}}public class Shape{public int Sides { get; set; }}public static class ShapeUtility{public static bool IsPolygon(this Shape shape){return shape.Sides >= 3;}public static void GenerateRandomSides(Shape shape){Random random = new Random();shape.Sides = random.Next(1, 6);}}
}

So to get over this issue, you can simply modify your code like this:

using System;
using static System.Console;
using static NewInCSharp.ShapeUtility;namespace NewInCSharp
{class Program{private static void Main(string[] args){Shape shape = new Shape();GenerateRandomSides(shape);/* You can write WriteLine(ShapeUtility.IsPolygon(shape));.
            But here I'm executing extension method on shape type,
            that's why they are called extension methods
            since there are just a extension of your type. duh! */WriteLine(shape.IsPolygon()); ReadLine();}}public class Shape{public int Sides { get; set; }}public static class ShapeUtility{public static bool IsPolygon(this Shape shape){return shape.Sides >= 3;}public static void GenerateRandomSides(Shape shape){Random random = new Random();shape.Sides = random.Next(1, 6);}}
}

Exception Filtering

Exception filtering is nothing but some condition attached to the catch block. Execution of the catch block depends on this condition. Let me give you a simple example.

In C# 5, we would have done something like the code given below to show users appropriate messages depending on the randomly generated http status codes.

using System;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){Random random = new Random();var randomExceptions = random.Next(400, 405);WriteLine("Generated exception: " + randomExceptions);Write("Exception type: ");try{throw new Exception(randomExceptions.ToString());}catch (Exception ex){if(ex.Message.Equals("400"))Write("Bad Request");else if (ex.Message.Equals("401"))Write("Unauthorized");else if (ex.Message.Equals("402"))Write("Payment Required");else if (ex.Message.Equals("403"))Write("Forbidden");else if (ex.Message.Equals("404"))Write("Not Found");}ReadLine();}}
}

Here, I'm randomly generating an exception code randomExceptions. Inside the catch block, I'm showing the appropriate error message respective to the exception code.

Now you can achieve the same thing using exception filtering but the syntax is a bit different. Rather than entering the catch block and checking to see which condition met our exception, we can now decide if we even want to enter the specific catch block. Here is the code:

using System;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){           Random random = new Random();var randomExceptions = random.Next(400, 405);WriteLine("Generated exception: " + randomExceptions);Write("Exception type: ");try{throw new Exception(randomExceptions.ToString());}catch (Exception ex) when (ex.Message.Equals("400")){Write("Bad Request");ReadLine();}catch (Exception ex) when (ex.Message.Equals("401")){Write("Unauthorized");ReadLine();}catch (Exception ex) when (ex.Message.Equals("402")){Write("Payment Required");ReadLine();}catch (Exception ex) when (ex.Message.Equals("403")){Write("Forbidden");ReadLine();}catch (Exception ex) when (ex.Message.Equals("404")){Write("Not Found");ReadLine();}}}
}

So, what's the main difference between these two. Well when you enter a catch block, the current execution state is lost. So, the actual cause of the exception is really hard to find. But in the exception filtering, we stay where we should be staying, i.e., current execution state. This means the stack stays unharmed.

So, exception filtering is good, right? Well there is a catch! Since in the exception filtering, entering a catch block depends on the filter applied on the catch, making a silly mistake can change the whole meaning of the exception. This may actually happen cause the filtering depends on a boolean result and this boolean result can be sent from any code block, making the exception have a different meaning. For example:

using System;
using System.Net.Http;
using System.Threading.Tasks;
using static System.Console;namespace NewInCSharp
{class Program{private static void Main(string[] args){Task.Factory.StartNew(GetWeather);ReadLine();}private static async void GetWeather(){string customErrorMessage;HttpClient client = new HttpClient();try{HttpResponseMessage httpResponseMessage = await client.GetAsync("http://api.openweathemap.org/data/2.5/weather?q=NewYorK");WriteLine(httpResponseMessage);}catch (Exception ex) when (DoASillyMistake(ex.Message, out customErrorMessage)){WriteLine(customErrorMessage);}}private static bool DoASillyMistake(string exceptionMessage, out string customErrorMessage){if (exceptionMessage.Equals("An error occurred while sending the request.")){customErrorMessage = "Unauthorized.";return true;}else{customErrorMessage = "Bad Gateway.";return true;}}}
}

This is a silly example I must say, but let's assume that if a request to a weather service fails, it's because of two reasons, one the service is not up and running [Bad Request] and the second is a user needs to be authorized before accessing the service [Unauthorized]. So, in my code, I know for sure that the HttpClient will throw an error message like below if it's a Bad Request.

Hide Copy Code

"An error occurred while sending the request."

Again for any other error messages, let's assume it's an Unauthorized request. If you look carefully at theDoASillyMistake(string exceptionMessage, out string customErrorMessage) function, you will see I really did a silly mistake. I've shown the user that they are 'Unauthorized' to access the service while the message should be 'Bad Request' since the service url is not valid [there is a letter is missing in the url; 'r' to complete the word weather]. Now the funny and bit irritating part is that the user will now start looking for a registration process to get access to the service. But sadly, we all know that is not the case. The funnier part is even if he registered himself, from now he will get a 'Bad Request'. So, you must be careful when using exception filtering.

But even this side effect can sometimes come in handy. For example, you can attach a filter function which logs error messages and returns false so that the log contains an appropriate exception and also the execution cursor doesn't end up in the catch block. Here is a good example from that I found in this open source .NET git repo documentation, New Language Features in C# 6.

private static bool Log(Exception e) { /* log it */ ; return false; }
....
try { .... } catch (Exception e) when (Log(e)) {}
 
 

Video Tutorial

The video tutorial for this article can be found at the following link:

  • What's new in C# 6.0

Points of Interest

So, these are some new features of C# 6.0 explained with some simple examples. To know more on what's coming next, be sure to keep your eye on this git repo documentation:

  • New Language Features in C# 6

Hope you enjoyed the post. Share it if you like.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

转载于:https://www.cnblogs.com/buyixiaohan/p/4784702.html

What's New in C# 6.0(转)相关推荐

  1. 估算带卷积核二分类0,3的网络的收敛时间和迭代次数

    制作一个网络分类minst的0和3求出这网络的迭代次数曲线表达式n(δ),和准确率表达式p-max(δ),用预期准确率去估算n,并推算需要的时间. 将minst的28*28的图片缩小到9*9,网络用一 ...

  2. 神经网络收敛标准与准确率之间的数学关系

    制作一个带一个3*3卷积核的神经网络,测试集是minst的0和2图片集,将28*28的图片缩小成9*9,隐藏层30个节点所以网络的结构是 S(minst0)-(con3*3)49-30-2-(1,0) ...

  3. 用共振频率去进行图片分类的尝试

    假设有一种物质,这种物质的原子核的质子数和电子数可以不同,允许质子的带电量不同,并且质子带负电,同时这个原子的电子不满足鲍利不相容原理,环境温度是 (1/1.3806505)*10^23k,电子波的频 ...

  4. 收敛标准对迭代次数影响

    制作一个n*n的网络,将收敛标准分别设定在,0.001,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,观察网络达到平衡时迭代次数的变化. 比如如图的 ...

  5. vue省市区三级联动mysql,js/json,html/jsp

    大家好,我是烤鸭: 省市区三级联动数据及页面: 测试的时候,发现少了几个地区,现在补上了,也优化了下排版. 如果你懒得复制和看的话,这里是打包的下载地址. 之前的资源地址也改了,http://down ...

  6. ZAM 3D 制作3D动画字幕 用于Xaml导出

    ZAM 3D 制作3D动画字幕 用于Xaml导出 原文:ZAM 3D 制作3D动画字幕 用于Xaml导出 原地址-> http://www.cnblogs.com/yk250/p/5662788 ...

  7. 将执行文件转化为bat批处理文件的工具(批处理文件方式提供)

    update 2006.4.25 15:20 支持64kb以上的执行文件/// @echo e 0100 4d 5a 90 0 3 0 0 0 4 0 0 0 ff ff 0 0 >>Da ...

  8. 完整的境外、港澳台、电信、移动、联通、教育网、国内其他ISP的IPv4列表(数据整理日期2022年4月)-IP列表太长只能份2篇发布(1/2)

    完整的境外.港澳台.电信.移动.联通.教育网.国内其他ISP的IPv4列表(数据整理日期2022年4月)-IP列表太长只能份2篇发布(1/2) 综述 境外(不含港澳台)IPv4地址 综述 企业所在地南 ...

  9. 聚宽JQData说明书

    由于内容较多,可使用Ctrl+F搜索您需要的数据. 注意:query函数的更多用法详见:sqlalchemy.orm.query.Query对象 JQData是什么 JQData是聚宽数据团队专门为金 ...

  10. 情人节程序员用HTML网页表白【520爱心背景3D相册】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript

    这是程序员表白系列中的100款网站表白之一,旨在让任何人都能使用并创建自己的表白网站给心爱的人看. 此波共有100个表白网站,可以任意修改和使用,很多人会希望向心爱的男孩女孩告白,生性腼腆的人即使那个 ...

最新文章

  1. java获取服务器信息吗_java获取服务器一些信息的方法
  2. Linux目录的基本说明
  3. linux虚拟机保存指令,vmware虚拟机命令保存
  4. Power Network POJ - 1459(EK算法模板+详解)
  5. 【libjpeg.lib】在Windows7下编译生成libjpeg.lib
  6. 面试题:不使用其他变量交换两个数字
  7. LINUX下载ant源码并编译
  8. 万能命令免费下载百度文库任意文档
  9. java httpsession 类型_JavaWeb HttpSession
  10. java操作seaweedfs
  11. 有感于《成都私车数量超上海》
  12. 洛谷P1330 封锁阳光大学(BFS, 并查集)
  13. npm ERR path /Users/user/Desktop/app/node_modules/node-sass
  14. 微信用户头像不能高清问题
  15. 无法加载操作系统,原因是关键系统驱动驱动程序丢失或包含错误 kisboot.sys
  16. 淘宝API卖家/买家相关接口列表与说明
  17. linux 解压war包
  18. gmail账号找回_如何找回忘记的Gmail密码
  19. java答辩记录问题,S2_javaWeb答辩问题集 qlzx
  20. Mysql 聚集索引和非聚集索引区别

热门文章

  1. ISA频繁断线的原因和解决方法
  2. 转载在linux下执行java窗口被锁定问题
  3. 常用NTP网络时间服务器整理
  4. MySQL数据库(九) 一一 处理重复和SQL注入
  5. (https)nginx - tomcat(http)
  6. JavaScript字符串替换replace方法
  7. MYSQL索引失效的各种情形总结
  8. MVP Open Day小记
  9. 《WCF技术内幕》翻译5:第1部分_第1章_蓝月亮:WCF介绍和本章小结
  10. mysql的未提示输入密码