C#7.0中新特征匯總。本站提示廣大學習愛好者:(C#7.0中新特征匯總)文章只能為提供參考,不一定能成為您想要的結果。以下是C#7.0中新特征匯總正文
以下將是 C# 7.0 中一切籌劃的說話特征的描寫。跟著 Visual Studio “15” Preview 4 版本的宣布,這些特征中的年夜部門將活潑起來。如今是時刻來展現這些特征,你也告知借此告知我們你的設法主意!
C#7.0 增長了很多新功效,並專注於數據花費,簡化代碼和機能的改良。也許最年夜的特征就是元祖和形式婚配,元祖可以很輕易地具有多個前往成果,而模子婚配可以依據數據的“形”的分歧來簡化代碼。我們願望,將它們聯合起來,從而使你的代碼加倍簡練高效,也能夠使你加倍快活並富有成效。
請點擊 Visual Studio 窗口頂部的反應按鈕,告知我們哪些是你不等待的特征或許你關於晉升這些特征的思慮。還有很多功效沒有在 Preview 4 版本中完成。接上去我會描寫一些我們宣布的終究版本裡將會起感化的特征,和一些一旦不起感化機即會刪除失落的特征。我也是支撐對這些籌劃作出轉變,特別是作為我們從你那兒獲得反應的成果。當終究版本宣布時,這些特征中的一些將會轉變或許刪除。
假如你獵奇這些特征的設計進程,你可以在 Roslyn GitHub site 上找到許多設計筆記和評論辯論。
願望 C#7.0 能帶給你快活!
輸入變量
在以後的 C# 中,應用輸入參數其實不像我們想的那樣便利。在你挪用一個無輸入參數的辦法之前,起首必需聲明一個變量並傳遞給它。假如你沒有初始化這些變量,你就沒法應用 var 來聲明它們,除非先指定完全的類型:
public void PrintCoordinates(Point p) { int x, y; // have to "predeclare" p.GetCoordinates(out x, out y); WriteLine($"({x}, {y})"); }
在 C#7.0 中,我們正在增長輸入變量和聲明一個作為可以或許被傳遞的輸入實參的變量的才能:
public void PrintCoordinates(Point p) { p.GetCoordinates(out int x, out int y); WriteLine($"({x}, {y})"); }
留意,變量是在關閉塊的規模內,所今後續也能夠應用它們。年夜多半類型的聲明不樹立本身的規模,是以在他們中聲明的變量平日會被引入到關閉規模。
Note:在 Preview 4 中,實用規模規矩更加嚴厲:輸入變量的感化域是聲明它們的語句,是以直到下個版本宣布時,下面的示例才會起感化。
因為輸入變量直接被聲明為實參傳遞給輸入形參,編譯器平日會告知他們應當是的類型(除非有抵觸過載),所以應用 var 來取代聲明它們的方法是比擬好的:
p.GetCoordinates(out var x, out var y);
輸入參數的一種罕見用法是Try形式,個中一個布爾前往值表現勝利,輸入參數就會攜帶所獲的成果:
public void PrintStars(string s) { if (int.TryParse(s, out var i)) { WriteLine(new string('*', i)); } else { WriteLine("Cloudy - no stars tonight!"); } }
留意:這裡i只用在 if 語句來界說它,所以 Preview 4 可以將這個處置的很好。
我們籌劃許可以 a* 為情勢的“通配符”作為輸入參數,這會讓你疏忽了你不關懷參數:
p.GetCoordinates(out int x, out *); // I only care about x
Note:在 C#7.0 中能否會包括通配符還不肯定。
形式婚配
C# 7.0 引入了形式概念。籠統地講,形式是句法元素,能用來測試一個數據能否具有某種“形”,並在被運用時,從值中提取有用信息。
C#7.0 中的形式示例:
•C 情勢的常量形式(C是C#中的常量表達式),可以測試輸出能否等於C
•T X 情勢的類型形式(T是一品種型、X是一個標識符),可以測試輸出能否是T類型,假如是,會將輸出值提取成T類型的新變量X
•Var x 情勢的 Var 形式(x是一個標識符),它老是婚配的,並簡略地將輸出值以它本來的類型存入一個新變量X中。
這僅僅是個開端 - 形式是一種新型的 C# 中的說話元素。將來,我們願望增長更多的形式到 C# 中。
在 C#7.0,我們正在增強兩個現有的具有形式的說話構造:
•is 表達式如今具有一種右手側的形式,而不只僅是一品種型
•switch 語句中的 case 語句如今可使用婚配形式,不只是常數值
在 C#的將來版本中,我們能夠會增長更多的被用到的形式。
具有形式的 IS 表達式
上面是應用 is 表達式的示例,個中應用了常量形式和類型形式:
public void PrintStars(object o) { if (o is null) return; // constant pattern "null" if (!(o is int i)) return; // type pattern "int i" WriteLine(new string('*', i)); }
正如你們看到,形式變量(形式引入的變量)和早前描寫的輸入變量比擬相似,它們可以在表達式中央聲明,並在比來的規模內應用。就像輸入變量一樣,形式變量是可變的。
注:就像輸入變量一樣,嚴厲規模規矩實用於Preview 4。
形式和 Try辦法可以很好地協同:
if (o is int i || (o is string s && int.TryParse(s, out i)) { /* use i */ }
具有形式的 Switch 語句
我們正在歸結 Switch 語句:
•可以設定任何類型的 Switch 語句(不只是原始類型)
•形式可以用在 case 語句中
•Case 語句可以有特別的前提
上面是一個簡略的例子:
switch(shape) { case Circle c: WriteLine($"circle with radius {c.Radius}"); break; case Rectangle s when (s.Length == s.Height): WriteLine($"{s.Length} x {s.Height} square"); break; case Rectangle r: WriteLine($"{r.Length} x {r.Height} rectangle"); break; default: WriteLine("<unknown shape>"); break; case null: throw new ArgumentNullException(nameof(shape)); }
關於新擴大的 switch 語句,有幾點須要留意:
•Case 語句的次序如今變得主要:就像 catch 語句一樣,case 語句的規模如今可以訂交,第一個婚配上的會被選中。另外,就像 catch 語句一樣,編譯器經由過程去除顯著不會進入的 case 來贊助你。在此之前,你乃至不須要告知斷定的次序,所以這其實不是一個應用 case 語句的偉大的轉變。
•默許的語句照樣最初被斷定:雖然 null 的 case 語句在最初語句之前湧現,它也會在默許語句被選中之前被測試。這是與現有 Switch 語義兼容的。但是,好的做法平日會將默許語句放到最初。
•Switch 不會到最初的 null 語句:這是由於以後 IS 表達式的例子具有類型婚配,不會婚配到 null。這包管了空值不會不當心被任何的類型形式婚配上的情形;你必需更明白若何處置它們(或廢棄它而應用默許語句)。
經由過程一個 case 引入形式變量:標簽僅在響應的 Switch 規模內。
元組
這是一個從辦法中前往多個值的罕見形式。今朝可選用的選項並不是是最好的:
•輸入參數:應用起來比擬愚笨(即便有上述的改良),他們在應用異步辦法是不起感化的。
•System.Tuple<...> 前往類型:冗余應用和要求一個元組對象的分派。
•辦法的定制傳輸類型:關於類型,具有年夜量的代碼開支,其目標只是臨時將一些值組合起來。
•經由過程靜態前往類型前往匿名類型:很高的機能開支,沒有靜態類型檢討。
在這點要做到更好,C#7.0 增長的元組類型和元組文字:
(string, string, string) LookupName(long id) // tuple return type { ... // retrieve first, middle and last from data storage return (first, middle, last); // tuple literal }
這個辦法可以有用地前往三個字符串,以元素的情勢包括在一個元組值裡。
這類辦法的挪用將會收到一個元組,而且可以零丁地拜訪個中的元素:
var names = LookupName(id); WriteLine($"found {names.Item1} {names.Item3}.");
Item1 等是元組元素的默許稱號,也能夠被一向應用。但他們不具有描寫性,所以你可以選擇添加更好的:
(string first, string middle, string last) LookupName(long id) // tuple elements have names
如今元組的吸收者有多個具有描寫性的稱號可用:
var names = LookupName(id); WriteLine($"found {names.first} {names.last}.");
你也能夠直接在元組文字指定元素稱號:
return (first: first, middle: middle, last: last); // named tuple elements in a literal
普通可以給元組類型分派一些彼此有關的稱號:只需各個元素是可分派的,元組類型便可以自若地轉換為其他的元組類型。也有一些限制,特殊是對元組文字,即罕見的和告警毛病,如失慎交流元素稱號的情形下,就會湧現毛病。
Note:這些限制還沒有在 Preview 4 中完成。
元組是值類型的,它們的元素是地下的,可變的。他們有值相等,假如一切的元素都是成對相等的(而且具有雷同的哈希值),那末這兩個元組也是相等的(而且具有雷同的哈希值)。
這使得在須要前往多個值的情形下,元組會異常有效。舉例來講,假如你須要多個 key 值的字典,應用元組作為你的 key 值,一切會異常順遂。假如你須要在每一個地位都具有多個值的列表,應用元組停止列表搜刮,會任務的很好。
Note:元組依附於一組根本類型,卻不包含在 Preview 4 中。為了使該特征任務,你可以經由過程 NuGet 獲得它們:
•右鍵單擊 Solution Explorer 中的項目,然後選擇“治理的NuGet包......”
•選擇“Browse”選項卡,選中“Include prerelease”,選擇“nuget.org”作為“Package source”
•搜刮“System.ValueTuple”並裝置它。
解構
消費元組的另外一種辦法是將解構它們。一個解構聲明是一個將元組(或其他值)朋分成部門並零丁分派到新變量的語法:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration WriteLine($"found {first} {last}.");
在解構聲明中,您可使用 var 來聲明零丁的變量:
(var first, var middle, var last) = LookupName(id1); // var inside
或許將一個零丁的 var 作為一個縮寫放入圓括號裡面:
var (first, middle, last) = LookupName(id1); // var outside
你也能夠應用解構義務來解組成現有的變量
(first, middle, last) = LookupName(id2); // deconstructing assignment
解構不只是運用於元組。任何的類型都可以被解構,只需它具有(實例或擴大)的解構辦法:
public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }
輸入參數組成懂得構成果中的值。
(為何它應用了參數,而不是前往一個元組?這是為了讓你針對分歧的值具有多個重載)。
class Point { public int X { get; } public int Y { get; } public Point(int x, int y) { X = x; Y = y; } public void Deconstruct(out int x, out int y) { x = X; y = Y; } } (var myX, var myY) = GetPoint(); // calls Deconstruct(out myX, out myY);
這是一種罕見的形式,以一種對稱的方法包括了構建息爭構。
關於輸入變量,我們籌劃在解構中參加通配符,來化簡你不關懷的變量:
(var myX, *) = GetPoint(); // I only care about myX
Note:通配符能否會湧現在C#7.0中,這還是未知數。
部分函數
有時刻,一個幫助函數可以在一個自力函數外部起感化。如今,你可以以一個部分函數的方法在其它函數外部聲明如許的函數:
public int Fibonacci(int x) { if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x)); return Fib(x).current; (int current, int previous) Fib(int i) { if (i == 0) return (1, 0); var (p, pp) = Fib(i - 1); return (p + pp, p); } }
閉合規模內的參數和部分變量在部分函數的外部是可用的,就好像它們在 lambda 表達式中一樣。
舉一個例子,迭代的辦法完成平日須要一個非迭代的封裝辦法,以便在挪用時檢討實參。(迭代器自己不啟動運轉,直到 MoveNext 被挪用)。部分函數異常合適如許的場景:
public IEnumerable<T> Filter<T>(IEnumerable<T> source, Func<T, bool> filter) { if (source == null) throw new ArgumentNullException(nameof(source)); if (filter == null) throw new ArgumentNullException(nameof(filter)); return Iterator(); IEnumerable<T> Iterator() { foreach (var element in source) { if (filter(element)) { yield return element; } } } }
假如迭代器有一個公有辦法傳遞給過濾器,那末當其它成員不測的應用迭代器時,迭代器也變得可用(即便沒有參數檢討)。另外,還會采用雷同的實參作為過濾器,以便調換規模內的參數。
留意:在 Preview 4,部分函數在挪用之前,必需被聲明。這個限制將會被松開,以便使得部分函數從界說分派中讀取時,可以或許被挪用。
文字改良
C#7.0 許可 _ 湧現,作為數字分隔號:
var d = 123_456; var x = 0xAB_CD_EF;
你可以將 _ 放入隨意率性的數字之間,以進步可讀性,它們對值沒有影響。
另外,C#7.0 引入了二進制文字,如許你便可以指定二進制形式而不消去懂得十六進制。
var b = 0b1010_1011_1100_1101_1110_1111;
援用前往和部分援用
就像在 C# 中經由過程援用來傳遞參數(應用援用修正器),你如今也能夠經由過程援用來前往參數,異樣也能夠以部分變量的方法存儲參數。
public ref int Find(int number, int[] numbers) { for (int i = 0; i < numbers.Length; i++) { if (numbers[i] == number) { return ref numbers[i]; // return the storage location, not the value } } throw new IndexOutOfRangeException($"{nameof(number)} not found"); } int[] array = { 1, 15, -39, 0, 7, 14, -12 }; ref int place = ref Find(7, array); // aliases 7's place in the array place = 9; // replaces 7 with 9 in the array WriteLine(array[4]); // prints 9
這是繞過占位符進入年夜數據構造的好辦法。例如,一個游戲或許會將它的數據保留在年夜型預分派的陣列構造中(為了不渣滓收受接管機制暫停)。辦法可以將直接援用前往成一個構造,經由過程它的挪用者可以讀取和修正它。
也有一些限制,以確保平安:
•你只能前往“平安前往”的援用:一個是傳遞給你的援用,一個是指向對象中的援用。
•當地援用會被初始化成一個當地存儲,而且不克不及指向另外一個存儲。
異步前往類型
到如今為止,C# 的異步辦法必需前往 void,Task 或 Task<T>。C#7.0 許可其它類型以這類能從一個辦法中前往的方法被界說,由於它們可以以異步辦法被前往的方法來界說其它類型。
例如我們籌劃樹立一個 ValueTask<T> 構造類型的數據。樹立它是為了避免異步運轉的成果在期待時已可用的情境下,對 Task<T> 停止分派。關於很多實例中設計緩沖的異步場景,這可以年夜年夜削減分派的數目並明顯地晉升機能。
Note:異步前往類型還沒有在 Preview 4 中供給。
更多的 expression bodied 成員:
expression bodied 的辦法和屬性是對 C# 6.0 的偉大晉升。C# 7.0 為 expression bodied 事宜列表增長了拜訪器,構造器和終結器。
class Person { private static ConcurrentDictionary<int, string> names = new ConcurrentDictionary<int, string>(); private int id = GetId(); public Person(string name) => names.TryAdd(id, name); // constructors ~Person() => names.TryRemove(id, out *); // destructors public string Name { get => names[id]; // getters set => names[id] = value; // setters } }
Note:這些額定增長的 expression bodied 的成員還沒有在 Preview 4 中供給。
這是社區同享的示例,而不是 Microsoft C# 編譯團隊供給的,照樣開源的!
Throw 表達式
在表達式中央拋出一個異常是很輕易的:只需為本身的代碼挪用一個辦法!但在 C#7.0 中,我們許可在隨意率性處所拋出一個表達式:
class Person { public string Name { get; } public Person(string name) => Name = name ?? throw new ArgumentNullException(name); public string GetFirstName() { var parts = Name.Split(" "); return (parts.Length > 0) ? parts[0] : throw new InvalidOperationException("No name!"); } public string GetLastName() => throw new NotImplementedException(); }
Note:Throw 表達式還沒有在Preview 4中供給。
以上所述是小編給年夜家引見的C#7.0中新特征匯總,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!