What's New in C# 6.0(转)
原文地址: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!");
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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!");
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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();
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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();
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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
*/
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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();
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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();
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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;
}
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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;
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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");
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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");
}
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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;
}
}
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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; } = "";
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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; } = "";
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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; } = "";
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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));
}
}
}
}
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));
}
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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));
}
}
}
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));
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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;
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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;
}
}
}
{
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;
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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);
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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);
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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);
}
}
}
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);
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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();
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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();
}
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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;
}
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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)) {}
....
try { .... } catch (Exception e) when (Log(e)) {}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Video Tutorial
The video tutorial for this article can be found at the following link:
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:
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)
What's New in C# 6.0(转)的更多相关文章
- ZAM 3D 制作简单的3D字幕 流程(二)
原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...
- ZAM 3D 制作3D动画字幕 用于Xaml导出
原地址-> http://www.cnblogs.com/yk250/p/5662788.html 介绍:对经常使用Blend做动画的人来说,ZAM 3D 也很好上手,专业制作3D素材的XAML ...
- 微信小程序省市区选择器对接数据库
前言,小程序本身是带有地区选着器的(网站:https://mp.weixin.qq.com/debug/wxadoc/dev/component/picker.html),由于自己开发的程序的数据是很 ...
- osg编译日志
1>------ 已启动全部重新生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake do ...
- 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)
0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...
- Elasticsearch 5.0 中term 查询和match 查询的认识
Elasticsearch 5.0 关于term query和match query的认识 一.基本情况 前言:term query和match query牵扯的东西比较多,例如分词器.mapping ...
- Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)
本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...
- vue2.0实践的一些细节
最近用vue2.0做了个活动.做完了回头发现,好像并没有太多的技术难点,而自己好像又做了比较久...只能说效率有待提升啊...简单总结了一些比较细节的点. 1.对于一些已知肯定会有数据的模块,先用一个 ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part3:db安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part3:db安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 5.安装Database软件 5. ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part1:准备工作 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 1.实施前准备工作 1.1 服务器安装操 ...
随机推荐
- 点击推送消息跳转处理(iOS)
当用户点击收到的推送消息时候,我希望打开APP,并且跳转到对应的界面,这就需要在AppDelegate里面对代理方法进行处理. 当用户点击推送消息打开APP的时候会调用 - (BOOL)applica ...
- 浅谈Block传值-匿名函数(代码块)
block传值是从后往前传值---代理也是 // 使用block时, 不能访问self, 也不能直接访问属性, self.属性, 用self调用方法; 只要这样做了, block都会对其强引用一份, ...
- 流输入练习——寻找Sb.VI codevs 3096
题目描述 Description 已知某开放授权人员名叫Serb,由于经常修改各种数据,因此开发人员们都喊他SB.现在他和许多人一起过飞机安检,排成了一长队列,请问SB.是否在队列中. 输入描述 In ...
- 织梦dedecms返回上一级链接代码
如题:织梦dede手机页面,如果我进入了下一级页面,想回上一级,<a href="xx">该用什么标签? 用JS实现,代码如下 <a href="jav ...
- mac qq截图功能失效后,如何重启截图功能?
在finder中打开应用程序目录,找到QQ,右键单击QQ,选择显示包内容,此时会打开一个文件夹. 进入以下路径Library/LoginItems然后双击ScreenCapture这个进程,截图功能即 ...
- sqlalchemy操作Mysql
SQLAlchemy“采用简单的Python语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型”.SQLAlchemy的理念是,SQL数据库的量级和性能重要于对象集合:而对象集合的抽象又 ...
- Hdu1091
#include <stdio.h> int main() { int a,b; while(scanf("%d %d",&a,&b)){ && ...
- OC和C语言的混编注意点和好处
苹果的Objective-C编译器批准用户在统一个源文件里自由地混杂利用C++和Objective-C,混编后的语言叫Objective-C++.有了它,你就能够在Objective-C利用过程中利用 ...
- bzoj 1912 巡逻(树直径)
Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Ou ...
- ArcGIS API for Silverlight开发入门
你用上3G手机了吗?你可能会说,我就是喜欢用nokia1100,ABCDEFG跟我 都没关系.但你不能否认3G是一种趋势,最终我们每个人都会被包裹在3G网络中.1100也不是一成不变,没准哪天为了打击 ...