日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C# 有什么惊艳到你的地方?

發布時間:2023/12/10 C# 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C# 有什么惊艳到你的地方? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:皮皮關
鏈接:https://www.zhihu.com/question/335137780/answer/786853293
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
?

很多游戲開發者都是由于Unity而“被迫”使用C#的。但用過一段時間,就會由衷贊嘆:真香。

如果有些同學沒感覺到很香,有可能是沒有仔細和其它語言比較 :)

1、C#良好兼容了值類型/引用類型,在發展中逐步解決了其他高級語言沒解決好的問題

縱觀主流語言,C語言在語法上是以值類型為基礎,借助指針實現引用類型;而Python/Lua等語言,是以引用類型為基礎。

論性能和細節控制力,C語言的設計上限更高;但是論簡易程度,Python更為統一、易用。這一基本矛盾在之前的語言里都沒有解決好。

而C#很好的總結了前人的經驗,在基礎語法上就區分了值類型和引用類型。對初次接觸編程的同學來說這一點容易造成學習障礙,但是只要掌握了它,就會給實際工作帶來極大便利。

反觀歷史,C#也曾經因為 值類型/引用類型 保守詬病,“拆箱”和“裝箱”一直是個招黑的設計。但后來我們看到,隨著泛型的成熟和普及,隨著泛型容器代替通用容器,裝箱和拆箱的問題已經在很大程度上解決了。

還有對異步的支持等等,C#的設計最初帶來了一些問題,但是最終還是交上了一份滿意的答卷。

2、充分利用棧空間,非常高效,做了一部分C/C++擅長的事

值類型有一大特點,就是能充分利用棧空間。高級語言的GC特性一直飽受詬病,但下面的Unity常見代碼,運行時沒有GC:

// 通過輸入的三維向量,移動物體的位置 void Move(Vector3 input) {// 演示代碼,有意分成很多行input = input.normalized;Vector3 move = input * 2.0f;move *= Time.deltaTime.transform.position += move; }

這段代碼沒有在堆上分配空間,你所看到的操作全都是在棧上進行的,GC壓力為0。我認為這是C#最令人驚艷的一點。

一般來說數組長度較長,默認分配在堆上。但是C#也提供了便利的語法,在棧上分配數組,對項目后期優化來說簡直是神技:

public void unsafe foo() {int* bar = stackalloc int [10]; }

沒錯,C#依然保留了指針,但一般僅用于局部的unsafe代碼。在局部熱點可以完全解放性能。

3、良好的語法設計和庫函數設計,引導程序員寫出更快且更自然的代碼

C#中最常用的容器List,也具有一些良好的設計(當然其它語言也有類似的優點)

// 新建一個list,長度為0。但在堆中預留10萬個位置List<int> list = new List<int>(100000);// 加入很多元素,由于容量足夠沒有GCfor (int i=0; i<89000; i++){list.Add(i);}// 用過以后清空list,長度變成0list.Clear();// 但容量還是10萬,繼續增加元素還是沒有GCfor (int i = 0; i < 99000; i++){list.Add(i);}

list在預留空間充足時,添加元素不會產生GC。而且List和值類型結合使用,在內存占用上也有優勢。當然,很多其它語言也有類似的設計,可以說別的語言做的好的部分,C#做的也一樣好。

4、繼承、泛型、接口、類型約束等等高級特性,都有著良好且自洽的設計

最初接觸C#的時候,看看int的原型,收獲很大:

public struct Int32 : IFormattable, IConvertible, IComparable, IComparable<Int32>, IEquatable<Int32>{// ....}

熟悉C++的人,經過思考,可以很好的理解IComparable、IEquatable以及它們的泛型形式。同時也能猜出“Interface”的概念。思考C#的底層設計,給人的感覺就是自然、規范、恰到好處。

總之,C#語言及其標準庫的設計,非常值得借鑒和推崇。

C#的良好設計讓它在游戲開發領域走出了一條光明大道,在其它領域也有著越來越廣泛的應用。

C#出現較晚,算是當今所有語言的集大成者?,F在它的發展主要受市場環境制約。也許幾年以后,會有新的語言在它的基礎上更上一層樓 :)

編輯于 2019-08-13

?贊同 298??70 條評論

?分享

?收藏?喜歡收起?

蔣國綱

技術宅男

76 人贊同了該回答

多接觸幾種語言,你會發現那些令其它語言開發者大呼驚艷的語言新特性其實都是C#玩剩的,我想這就是C#最驚艷的地方

發布于 2019-07-16

?贊同 76??17 條評論

?分享

?收藏?喜歡

懶得勤快

masuit.com,互聯網分享精神,勤于發現,樂于分享。

?

專業 已有 1 人贈與了專業徽章

?

208 人贊同了該回答

作為一名集.NET、JavaEE、web前端于一身的全棧開發者,我自認為我對C#、java、javascript的認知都不算很淺的了,如果我們可以同時擁有 C# 和 Java 世界的最好特性,那會是什么樣呢?

?

?

完美的編程語言并不存在,我希望我們可以在這一點上達成一致。開發新語言往往是為了克服另一種語言的弊端,又不可避免的在某些方面上健壯一些,卻在另一些方面上存在不足。

  C# 與 Java 都起源于 C/C++ 語言,他們在面向對象方面有許多相似之處。除了 Java JVM 和 C# .NET CLR 有許多相同結構上的相似性之外,他們各自的開發團隊都有各自的發展方向,他們關注的是各自的語言應該成為什么樣子。

  我們并不想糾結于某一個語言比另一個語言好,我們只想羅列出 C# 開發者能用到而 Java 中沒有的那些特性而已。

  下面我們開始吧。

1. LINQ

  LINQ (Language-Integrated Query,語言集成查詢) 于 2007 年引入到 C#,以幫助開發人員從各種數據源查詢數據。使用它,我們可以在無需考慮正在調用的特定數據庫的語法來編寫查詢語句。LINQ provider 所提供的一個組件將查詢轉換為下層數據源可讀的格式。例如,如果我們需要從 SQL 數據庫查詢數據,LINQ to SQL provider 程序將把 LINQ 查詢轉換成 T-SQL,以便數據庫可以理解它。

  要在 LINQ 中執行查詢操作,首先獲取數據庫,然后創建查詢,最后執行查詢。在 LINQ to Object 查詢中,這可能僅像一樣代碼一樣簡單,而不是為每個循環編寫嵌套的復雜迭代。

  例如,我們來看看這個代碼,用于在 C# 中從列表中過濾 2 位數。

  首先,在不使用 LINQ 的情況下:

List<int> FilterTwoDigitNumbersWithoutLinq(List<int> numbers) {var tens = new List<int>();for (var i=0; i < numbers.Count(); i++){if ((9 < numbers[i]) && (numbers[i] < 100)){tens.Add(numbers[i]);}}return tens; }

  如果使用 LINQ 查詢語法形式:

List<int> FilterTwoDigitNumbersWithLinq(List<int> numbers)=>(from a in numbers where (a > 9 && a < 100) select a).ToList();

  或者是方法語法形式:

List<int> FilterNonTwoDigitNumbersWithLinq2(List<int> numbers)=> numbers.Where(a => a > 9 && a < 100).ToList();

  這里兩種語法都是正確的,唯一的區別就是查詢語法看起來更像是 SQL 語句而方法語法使用 lambda 表達式(當然,看起來很像我們在 Java 里寫的某些代碼)

  綜述:LINQ 所依賴的許多特性,如 lambda 表達式(就 LINQ 來說非常有用),已經在 Java 中有了等效的實現,盡管我們可以使用流和 lambda 來查詢數據,但 LINQ 簡化了整個過程并且移除了很多在 Java 中存在的冗余代碼。

2. Struct

  C# 中的結構體類似于類。實際上,一個 struct 甚至可以被認為是一個“輕量級類”,因為它可以包含構造函數、常量、方法等等。一個結構體和一個類之間最大的區別在于結構是值類型,而類是引用類型。

  相比于創建類,編寫結構體最重要的好處是在構造一個值類型時比在構造引用類型時更容易確保值語義。如 Microsoft 的文檔所述,“struct 類型的變量直接包含結構體的數據,而類類型的變量包含對數據的引用。”因此,對比使用類時,使用結構體的好處之一是,從代碼的其他部分更改其值的唯一方法是將其作為參考進行顯式傳遞。

  微軟的開發人員建議對于那些小于 16 字節、生命周期短、不改變的而且不常裝箱的類型,使用結構體(struct)而不是類(class)。在這種情況下,使用結構體可能會比使用類更有效率,因為它會保存在棧而不是堆中。

  比如:

public struct Point {public int X;public int Y;public Point(int X, int Y){this.X = X;this.Y = Y;}public static Point operator +(Point p1, Point p2){return new Point(p1.X + p2.X, p1.Y + p2.Y);}public override string ToString(){return ($"({X}, {Y})");} } class Program {static void Main(string[] args){Point point1 = new Point(1, 5);Point point2 = new Point(2, 3); Console.WriteLine("兩個點相加的結果是: {0}", (point1 + point2)); Console.ReadKey();} }

  小結:很多情況下使用結構體可以節省內存分配和釋放的時間,這確實很有吸引力。然而事實是值類型擁有自己的存儲空間。無論結構體擁有如何明顯的優點和缺點,這在 Java 中都不需要操心。

3. async/await

  在一段代碼中調用 async,或者更明確地調用方法,這個方法都會在另一個線程上執行,不會阻塞當前線程。當代碼運行到 await 命令的時候,它會繼續運行(await 的語句)。如果這時 async 代碼還沒有完成,那么執行中的程序會返回到調用點。

  這有助于提高應用程序總體的響應速度,以及減少性能瓶頸。在應用程序訪問 Web 和進行所有 UI 相關的活動時,使用異步程序非常重要。相對于以前的異步編程實現,使用 async/await 可以保留你代碼的邏輯結構,而編譯器則會擔負起以前由開發者擔負的重擔。

  示例:

class Program{public static void Main(){Console.WriteLine("Hey David, How much is 98745 divided by 7?");Task<int> david = ThinkAboutIt();Console.WriteLine("While he thinks, lets chat about the weather for a bit.");Console.WriteLine("Do you think it's going to rain tomorrow?");Console.WriteLine("No, I think it should be sunny.");david.Wait();var davidsAnswer = david.Result;Console.WriteLine($"David: {davidsAnswer}");Console.ReadKey();}private static async Task<int> ThinkAboutIt(){await ReadTheManual();Console.WriteLine("Think I got it.");return (98745 / 7);}private static async Task ReadTheManual(){string file = @"D:\HowToCalc.txt";Console.WriteLine("Reading a manual.");using (StreamReader reader = new StreamReader(file)){string text = await reader.ReadToEndAsync();}Console.WriteLine("Done.");} }

  輸出:

// Possible Output: Hey David, How much is 98745 divided by 7? Reading a manual. While he thinks, lets chat about the weather for a bit. Do you think it's going to rain tomorrow? No, I think it should be sunny. Done. Think I got it. David: 14106

  概要:CompletableFutures 無疑可以使我們更趨近于擁有等效于 C# 和 Java 所擁有的異步編程中的能力。盡管如此,使用它所帶來的復雜性使其易用度不能與使用 async /await 關鍵字進行的實現相提并論。

4. Lazy<T> 類

  無論使用 C# 還是 Java,很多人都已經實現了延遲初始化 (或實例化),因此對象要在第一次使用的時候才會被創建。有一種常見的例子是將延遲初始化用于應用程序啟動的時候加載大量對象,但實際需要初始化的對象可能只有少數幾個。這種情況下,我們希望辨別哪些是不需要在這里初始化的。只初始化那些確實需要初始化的對象可以提升應用程序的性能。

  小結:最近,Lambda 表達式引入到 Java 8 之后,在 Java 中實現延遲加載(還有不少其它事情)變得更容易了。不過,在 C# 中我們可以使用語義化的 Lazy<T> 封裝類來延遲初始化任何類庫或用戶指定的類型。

5. 一些等價的關鍵詞

  語言中的有用功能不一定像在 C# 中的 LINQ 或 Java 中的模塊一樣大。這里有一些可以幫助 C# 開發人員的關鍵字,它們在 Java 中并沒有:

  a. as

  C# 中的 as 關鍵字會嘗試安全地將對象轉換為某個類型,如果不能轉換的話,就返回 null。與 Java 的instanceof 幾乎等同,但它是一個布爾值,如果類型匹配則返回 true,否則返回 false。

  b. yield

  在 C# 中使用 Yield 和 return yield 來進行自定義且狀態化的迭代,不需要顯式創建額外的類,也不需要創建臨時集合。在 Java 中我們實現迭代最好的選擇是使用外部庫或使用 Java 8 引入的 Lambda 表達式。

  c. var

  var 是一種自動推斷類型,也可以稱之為萬能接口,其實際類型由編譯器決定,其功能相當于寫一個顯式類型 (比如 int, string 等)。它除了可以減少一些按鍵之外,var 還允許用于匿名類型,而匿名類型在 LINQ 中很常用。我們期待看到“var”標識,備受矚目的 Java SE 9 將實現“將類型推導擴展到定義并初始化局部變量時?!?/p>

  d. checked

  C# 中,我們使用 checked 關鍵字顯式啟用對整型表達式的溢出檢查。如果表達式的運算結果超出目標類型的范圍,我們可以使用 checked 強制要求運行時拋出 OverflowException。這十分有用,因為常量表達式會在編譯期進行溢出檢查,而非常量表達式不會。

工具生態系統

  Java 和 C# 之間存在大量的不同之外,當然,其中一些源于 Java 和 .NET 框架的不同。這些不同之處也導致了一些工具在兼容性方面的差異,比如 OverOps 在生產監控和錯誤跟蹤方面的差異。

  OverOps 向開發者展示生產中每個錯誤整個調用棧的全部源代碼和變量狀態。目前在 .NET 框架上并沒有與之相同的內容,不過在接下來的幾個月內會有一些變化。想了解更多信息,請點擊這里加入我們 .NET Beta 的等候名單,如果你是 Java 開發者可以去 http://www.overops.com 查看演示。

最后的思考

  在快結束時候,我們這里提到的大部分功能都在代碼長度和簡潔程度方面對 C# 開發者有所幫助,這些代碼不能在 Java 中編寫。事實上這些特性也或多或少說明了 Java 語言冗長的問題,包括最近版本更新帶來的 Lambda 表達式。誠然,很多這些存在于 C# 而不存在于Java 中的特性在常規使用中提供了比使用 Lambda 更簡潔的語法。

  再次說明,我們不想卷入沒完沒了的關于哪種言更好的爭論,我們只是在這里指出兩種語言之間的一些區別。我們是否遺漏了某些你希望 Java 擁有的特性?請在評論中告訴我們!

總結

以上是生活随笔為你收集整理的C# 有什么惊艳到你的地方?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。