C# 6.0

 

C#已經推進到6.0了,我想一些新的語法還是有必要了解一下,

C#6.0是roslyn編譯器所支援,而roslyn是被內建在VS2015,

雖然VS2013可以透過Nuget安裝Microsoft.Net.Compilers來使用C#6.0,

但可能會有未知的相容問題,所以想要使用C#6.0新功能建議是使用VS2015。

 

一、自動屬性初始化 Setting default values to Auto Properties

以往自動屬性初始值無法直接指定,必須要寫在建構函式,

現在可以直接對自動屬性設定初始值

public string Name { get; set; } = "Brooke";

而C#5.0以前,自動屬性必須包含get與set,

現在C#6.0允許你可以做自動屬性唯讀初始化

public string Name { get; } = "Brooke";

 

二、使用 using 靜態命名類別

於C#6.0可以直接using 靜態命名類別,用法跟using命名空間很像,

只要是靜態類別,則可以使用 using static關鍵字,把類別當成命名空間來使用

using System;
using static System.Math;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine(Abs(-10));
            Console.ReadKey();
        }
    }
}

 

三、String Interpolation

以前string.Format舊的寫法

string name = string.Format("FullName:{0},{1}", m.FirstName, m.LastName);

而使用「字串插補」功能後,新的寫法,$"{變數}"

name = $"FullName:{m.FirstName} , {m.LastName}";

也就是說String.Format( "{0}{1}" , x , y );格式會被簡化成 $"{x}{y}";
我還看過有人還會在字串插補功能再加上if判斷式,蠻令人驚奇的。

var s = $"{m.FirstName} is {m.age} year{(m.age == 1 ? "" : "s")} old";

範例如下(感謝Wesley Huang指正)

using System;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };

            string name = string.Format("FullName:{0},{1}", m.FirstName, m.LastName);
            name = $"FullName:{m.FirstName} , {m.LastName}";
            var s = $"{m.FirstName} is {m.age} year{(m.age == 1 ? "" : "s")} old";

            Console.WriteLine(name);
            Console.WriteLine(s);
            Console.ReadKey();
        }
    }
    class Person
    {
        public string FirstName;
        public string LastName;
        public int age;
    }
}

 

四、Expression-bodied function members
於 C#5.0 以前類別屬性與方法還無法使用 lambda 運算式

using System;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
            Console.WriteLine(m.FullName);
            Console.ReadKey();
        }
    }

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int age { get; set; }
        public string FullName { get { return FirstName + LastName; } }
    }
}

但是現在 C#6.0 的類別屬性與方法已經可以使用 lambda 運算式了
1、屬性

using System;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
            Console.WriteLine(m.FullName);
            Console.ReadKey();
        }
    }

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int age { get; set; }
        public string FullName => $"{FirstName}{LastName}";
    }
}

2、方法

using System;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
            Console.WriteLine(m.FullName());
            Console.ReadKey();
        }
    }

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int age { get; set; }
        public string FullName() => $"{FirstName}{LastName}";
    }
}

 

五、索引初始設定式(Dictionary Initializer)
以前索引初始化都使用以下格式

var numbers = new Dictionary<int, string>()
{
    { 1, "tom"},
    { 2, "bob"},
    { 3, "tim"},
};

現在改為

var numbers1 = new Dictionary<int, string>()
{
    [1] = "tom",
    [2] = "bob",
    [3] = "tim",
};

範例:

using System;
using System.Collections.Generic;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            var numbers = new Dictionary<int, string>()
            {
                { 1, "tom"},
                { 2, "bob"},
                { 3, "tim"},
            };

            var numbers1 = new Dictionary<int, string>()
            {
                [1] = "tom",
                [2] = "bob",
                [3] = "tim",
            };

            Console.WriteLine(numbers1[1]);
            Console.ReadKey();
        }
    }
}

 

六、Null-conditional operators「?.」、「?[]」
一般null條件判斷會這樣寫

private static int? GetFirstNameLength(Person person)
{
    int? result = null;
    if (person == null || person.FirstName == null)
    {
        return null;
    }
    result = person.FirstName.Length;
    return result;
}

而現在可以用問號取代 == null ||,如person? ||,意思為如果person等於null時則||左邊為true;
也同義於問號取代 != null &&,如person? &&,意思為如果person不等於null時則&&左邊為true

 

using System;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            Person Person = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
            Console.WriteLine(GetFirstNameLength(Person));
            Console.ReadKey();
        }

        private static int? GetFirstNameLength(Person person)
        {
            int? result = null;
            //if (person == null || person.FirstName == null)
            //{
            //    return null;
            //}
            result = person?.FirstName?.Length;
            return result;
        }
    }

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int age { get; set; }
        public string FullName => $"{FirstName}{LastName}";
    }
}

上例GetFirstNameLength()的意思同於如果person為null時則直接回傳null,若否,

則繼續判斷FirstName是否為null,若是,則直接回傳null,若否,

則回傳FirstName的字串長度。

整個運作方式是如果左側為Null則整個運算式都是Null,

如果左側不是Null則會以點屬性表示,並成為結果。

再舉另一例子,請參考。(感謝佑翔指正)

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //C#5.0之前
            string data = "Some String";
            var test = data != null ? data.Substring(0, 4) : string.Empty;
            Console.WriteLine(test);

            //C#6.0之後
            string data2 = "Some String";
            var test2 = data2?.Substring(0, 4);
            Console.WriteLine(test2);

            Console.ReadLine();
        }
    }
}

 

七、nameof運算子

nameof運算子功能是回傳方法或是屬性的名稱,這功能配合try catch偵錯回傳訊息會非常有幫助。

using System;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine(nameof(GetName));
            Console.ReadKey();
        }

        private static string GetName()
        {
            return "tom";
        }
    }
}

以下為回傳屬性名稱

using System;

namespace ConsoleApplication1
{
    class SampleClass
    {
        public string ID { get; set; } = "A123456789";
        public string Name { get; set; } = "Brooke";
    }

    class Program
    {
        static void Main(string[] args)
        {
            var SampleClass = new SampleClass();
            Console.WriteLine("{0} : {1}" ,nameof(SampleClass.ID),SampleClass.ID);
            Console.WriteLine("{0} : {1}",nameof(SampleClass.Name),SampleClass.Name);
            Console.ReadKey();
        }
    }
}

 

八、例外過濾
增加when語句來決定是否進入指定的catch區段,如下範例,當例外訊息包含了keyErrot字串時則另做處理,否則拋出例外

private static void CatchWhen()
{
    try
    {
        var r = 0;
        r = 0 / 0;
    }
    catch (Exception ex) when (ex.Message.Contains("keyError"))
    {
        Console.WriteLine("have handle exception");
    }
    catch (Exception ex)
    {
        throw;
    }
}

 

九、例外使用非同步
於C#6.0 catch跟finally區段也能用await了,如下範例

using System;
using System.Threading.Tasks;

namespace C_Sharp6
{
    class Program
    {
        static void Main()
        {
            CatchWhen();
            Console.ReadKey();
        }

        private static async void CatchWhen()
        {
            try
            {
                var r = 0;
                r = 0 / 0;
            }
            catch (Exception ex) when (ex.Message.Contains("keyError"))
            {
                Console.WriteLine("have handle exception");
                await Task.Delay(500);
            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                await Task.Delay(500);
            }
        }
    }
}

 

參考資料:

What's New in C# 6