<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          寫好C#代碼的技巧

          共 9151字,需瀏覽 19分鐘

           ·

          2020-10-11 05:41

          寫好C#代碼的技巧

          編者導語


          本文來自https://www.pluralsight.com,作者Afzaal Ahmad Zeeshan。

          原文包含以下三篇文章:

          《編寫更好的C#代碼簡介》https://www.pluralsight.com/guides/introduction-to-writing-better-csharp-code

          《編寫更好的C#代碼的技巧》https://www.pluralsight.com/guides/tips-for-writing-better-c-code

          《有關(guān)編寫更好的C#代碼的更多技巧》https://www.pluralsight.com/guides/more-tips-for-writing-better-csharp-code

          雖然本文僅介紹了C#6.0語言特性,而現(xiàn)在最新的C#已經(jīng)到了9.0,但這些內(nèi)容已經(jīng)仍然常讀常新。

          一、簡介

          C#已從C#5更改為C#6,為使項目更具可讀性,基于最佳標準的實踐也得到了發(fā)展。

          本指南系列的目的是幫助您為在團隊環(huán)境中運行的C#項目和.NET Framework應用程序編寫更簡潔的代碼。在團隊環(huán)境下,編寫好的代碼對開發(fā)人員可能更容易,因為編寫的代碼將由團隊中其他開發(fā)人員使用,管理和更新,而代碼質(zhì)量往往取決于您個人團隊的“哲學”和開發(fā)人員的編碼實踐。

          在這種情況下,最好的方法是遵循編碼團隊的準則,并為應用程序項目中的C#程序添加設(shè)計和風格,以使它們對讀者更好。請注意,C#編譯器并不關(guān)心您放入代碼中的風格。但我們以一種使C#應用程序?qū)ψx者來說看起來更簡單,更清潔,將更容易的方式更深入地進行編程,同時保持代碼開發(fā)的性能和效率。

          在閱讀本指南之前,您應該了解以下幾點:

          1.第6版對C#的改進2..NET框架中的LINQ3.TaskC#中的異步編程和對象4.使用C#進行的不安全編程,使您無法正常的使用內(nèi)存管理

          不專注于性能

          應該注意的是,我不會談論改變程序性能,提高效率或減少程序運行所花費的時間。通過編寫簡潔的C#代碼,您可以在幾秒鐘內(nèi)提高程序性能,但是以下技巧并不能保證您的代碼性能更好。

          為什么要編寫整潔的代碼?

          您編寫代碼,編譯器編譯時沒有警告也沒有錯誤,代碼很好。但是,如果其他人想讀出該代碼怎么辦?如果有人后來需要為您或您所在的公司升級代碼,該怎么辦?看下面的代碼:

          public static void Main(string[] args) {  int x = 0;  x = Console.Read();
          Console.WriteLine(x * 1.5);}

          該程序運行良好,系統(tǒng)中沒有錯誤,應用程序也可以正常工作。但是您能告訴我該程序在現(xiàn)實生活中做什么嗎?以下是可以做出的一些假設(shè):

          1.它只是乘以價值2.就像獎金一樣,它正在增加價值3.是個人銀行存款總額的利率4.等等。

          哪一個是真實的?沒有人會知道。在這種情況下,最好編寫出良好的代碼,并記住遵循編程的基礎(chǔ)。看下面的代碼:

          public static void Main(string[] args) {  int salary = 0;  salary = Console.Read();
          Console.WriteLine(salary * 1.5);}

          這比以前的代碼有意義嗎?我們可以很容易地說這個代碼將增加薪水的價值。請注意,僅通過改進代碼,我們就能確保其他人可以比以前更快地理解它。

          在本指南中,我不會向您展示如何遵循最佳原則。相反,我將以您已有的知識為基礎(chǔ),并教您如何充分利用C#程序。我將重點介紹如何在應用程序中編寫良好的C#邏輯,因此您將看到通過以這種方式和結(jié)構(gòu)編寫程序,可以從應用程序中獲得很多好處。

          因此,讓我們開始吧。

          對象初始化

          C#是一種面向?qū)ο蟮木幊陶Z言。如果對象本身沒有分塊,那么寫一組提示有什么好處?本節(jié)將重點介紹在前進并new Object()在應用程序中編寫代碼之前應考慮的事項。您必須了解如何創(chuàng)建C#類以及事物如何協(xié)作以在系統(tǒng)中啟動一個小程序。

          例如,看下面的代碼:

          class Person {  public int ID { get; set; }  public string Name { get; set; }  public DateTime DateOfBirth { get; set; }  public bool Gender { get; set; }}

          您可能想要創(chuàng)建默認情況下設(shè)置值的程序,或者讓它們來自模型或諸如此源代碼的任何其他面向數(shù)據(jù)庫的數(shù)據(jù)源,這些程序簡化了在對象時輸入默認值的方式正在創(chuàng)建。

          var person = new Person { ID = 1, Name = "Afzaal Ahmad Zeeshan", DateOfBirth = new DateTime(1995, 08, 29), Gender = true };

          相反,請嘗試通過以下方式編寫相同的代碼:

          var person = new Person();person.ID = 1;person.Name = "Afzaal Ahmad Zeeshan";// So on.

          這里的代碼沒有明顯的性能改進,但是可以真正提高代碼的可讀性。如果您喜歡縮進,請在這里查看:


          var person = new Person{  ID = 1,  Name = "Afzaal Ahmad Zeeshan",  DateOfBirth = new DateTime(1995, 08, 29),  Gender = true};

          這也有縮進,但是它為您的C#代碼的可讀性添加了更多的說明。盡管前面的代碼可以實現(xiàn)相同的功能,但是建議的代碼可以使代碼更易讀和簡潔。

          二、技巧

          空檢查

          NullReferenceException當缺少初始化的對象再次拋出異常時,您是否曾經(jīng)對感到惱火?在程序中進行空檢查有很多好處,不僅可以提高可讀性,而且可以確保程序不會由于內(nèi)存問題而終止(例如,內(nèi)存中不存在變量時)。這些可能與程序的安全性以及團隊具有的良好UI和UX準則相抵觸。大多數(shù)情況下,由于以下原因會引發(fā)空異常:

          string name = null;
          Console.WriteLine(name);

          在大多數(shù)情況下,除非您解決此問題,否則編譯器本身不會繼續(xù)運行,但是如果您設(shè)法以某種方式誘使編譯器認為變量具有值,但在運行時沒有變量,則會出現(xiàn)空引用異常。為了克服這個問題,您可以執(zhí)行以下操作:


          string name = null;
          // Try to enter the value, from somewhereif(name != null) { Console.WriteLine(name);}

          此安全檢查將確保在調(diào)用此變量時該值可用。否則,它將影響您代碼的路徑。但是,在C#6中,還有另一種方法可以克服此錯誤??紤]以下情形:建立數(shù)據(jù)庫,建立數(shù)據(jù)表,找到您的人員但找不到他們的就業(yè)詳細信息。你能找到他們工作的公司嗎?

          var company = DbHelper.PeopleTable.Find(x => x.id == id).FirstOrDefault().EmploymentHistory.CompanyName; // Error

          如果您這樣做,將會出現(xiàn)錯誤,因為我們只能在這些值的列表中進行簡單幾步的對象篩選。然后我們將碰到一個空值,一切都丟失了。C#6提出了一種克服這些情況的新方法,方法是在值和字段可以為null的后面使用安全的導航運算符。?.。像這樣:

          var company = DbHelper?.PeopleTable?.Find(x => x.id == id)?.FirstOrDefault()?.EmploymentHistory?.CompanyName; // Works

          如果前一個不為null,則此代碼僅檢查下一個值。如果先前的值為null,它將返回null并將null保存為的值company,而不是引發(fā)錯誤。將檢查留給框架本身可以很方便,但是,盡管如此,您仍然必須在最后檢查其余值是否為null。

          var company = DbHelper.PeopleTable?.Find(x => x.id == id)?.FirstOrDefault()?.EmploymentHistory?.CompanyName;
          if(company != null) { // Final process}

          但是您明白了這一點,而不是編寫代碼并檢查所有內(nèi)容是否為空,而是可以執(zhí)行簡單的檢查并執(zhí)行程序中想要的操作和邏輯。否則,將需要try...catch包裝器或多個if...else塊來控制程序在系統(tǒng)中的導航方式。

          異步編程模式

          如果您正在使用C#5進行編程,那么您已經(jīng)在使用async / await關(guān)鍵字為您的應用程序帶來改進。如果不是這種情況,那么我建議您在應用程序的源代碼中使用異步編程模式。這不僅可以提高對程序的響應速度,還可以提高應用程序的可讀性。在源代碼中具有異步模式的一些好處是:

          1.代碼路徑開始變得更加有意義。如果有一個進程在后臺開始運行,那么程序員可以了解程序應該在哪里。2.應用程序掛起問題將消失。大多數(shù)與應用程序阻塞相關(guān)的問題直接來自代碼。當UI線程無法更新UI時,用戶會認為該應用程序正在掛起并且沒有響應,而事實并非如此。異步方法確實可以幫上大忙。3.基于Windows運行時的應用程序完全基于此方法。您將(并且必須是!)在您的Windows Runtime應用程序中使用這種方法來解決諸如掛起應用程序或不良的編程習慣之類的問題。

          自從線程化以來,代碼執(zhí)行的并行化就已經(jīng)存在。異步已經(jīng)成為程序和應用程序的重要組成部分,因此您更應該考慮使用它。

          C#字符串構(gòu)建

          字符串是當今應用程序的重要組成部分,構(gòu)建字符串可能會花費很多時間,并且還會導致應用程序性能下降。您可以通過多種方式在C#程序中構(gòu)建字符串。以下是其中幾種方式:

          string str = ""; // Setting it to null would cause additional problems.
          // Way 1str = "Name: " + name + ", Age: " + age;
          // Way 2str = string.Format("Name: {0}, Age: {1}", name, age);
          // Way 3var builder = new StringBuilder();builder.Append("Name: ");builder.Append(name);builder.Append(", Age: ");builder.Append(age);str = builder.ToString();

          請注意,C#中的字符串是不可變的。這意味著,如果您嘗試更新它們的值,則會重新創(chuàng)建它們,并從內(nèi)存中刪除以前的句柄。這就是為什么方式1看起來是最好的方式,但經(jīng)過進一步思考,事實并非如此。最好的方法是方法3,它使您可以構(gòu)建字符串而不必在內(nèi)存中重新創(chuàng)建對象。同時,C#6引入了一種全新的方式在C#中構(gòu)建字符串,該方式比您以前想象的要好得多。新的

          字符串插值?運算符$為您提供了以最佳方式執(zhí)行字符串構(gòu)建的功能。字符串插值如下所示:


          static void Main(string[] args){   // Just arbitrary variables   string name = "";   int age = 0;
          // Our interest string str = $"Name: {name}, Age: {age}";}

          只需一行代碼,編譯器就會自動將其轉(zhuǎn)換為string.Format()版本。為了證明這一點,將詳細說明此C#程序已生成的字節(jié)碼,并向您展示如何自動更改語法以讀取字符串格式。

          IL_0000:  nopIL_0001:  ldstr       ""IL_0006:  stloc.0     // nameIL_0007:  ldc.i4.0IL_0008:  stloc.1     // ageIL_0009:  ldstr       "Name: {0}, Age: {1}"IL_000E:  ldloc.0     // nameIL_000F:  ldloc.1     // ageIL_0010:  box         System.Int32IL_0015:  call        System.String.FormatIL_001A:  stloc.2     // strIL_001B:  ret

          可以看出,這顯示了如何將語法更改回我們已經(jīng)看到的語法。有關(guān)IL_0009更多信息,請參見。當其他人正在讀取程序時,這可以使您的程序外觀更簡潔,并且如果要構(gòu)建的字符串較小,則可以提高性能。如果字符串較大,請使用StringBuilder。

          三、更多技巧

          遍歷數(shù)據(jù)

          如果不對一組數(shù)據(jù)進行循環(huán)和迭代,那么應用程序有什么用?在這種情況下,有時您將不得不查找值,查找節(jié)點,查找記錄或?qū)线M行任何其他遍歷。在這種情況下,您確實需要確保編寫干凈的代碼,因為這是性能和可讀性都非常重要且相互關(guān)聯(lián)的領(lǐng)域。

          有了一些經(jīng)驗,我就克服了編寫用于讀取和遍歷數(shù)據(jù)的錯誤代碼的方式。這正是LINQ應該加入的地方,LINQ允許您編寫使用最佳.NET框架為用戶和客戶提供最佳編碼體驗和最佳體驗的程序。

          以前,您可能已經(jīng)做過以下一些事情:

          6// A function to search for peoplePerson FindPerson(int id) {   var people = DbContext.GetPeople(); // Returns List
          foreach (var person in people) { if(person.ID == id) { return person; } }
          // No person found. return null;}
          // Then do thisvar person = FindPerson(123);

          對于任何想接手您代碼的人來說,這都是一段易讀的代碼。但是,使用C#中的LINQ查詢可以使代碼更加簡單和整潔。您可以通過兩種方式執(zhí)行此操作。一個有點像SQL,另一個是通過Where在集合上使用該函數(shù)并傳遞我們的要求。

          // A function to search for peoplePerson FindPerson(int id) {   var people = DbContext.GetPeople(); // Returns List
          return (from person in people where person.ID == id select person).ToList().FirstOrDefault();}
          // Then do thisvar person = FindPerson(123);

          該代碼看起來有點像SQL,可以增強代碼的可讀性和性能。該函數(shù)相似,但是,該Where函數(shù)的讀取效果更好,并使所有迭代都針對.NET框架本身,而.NET框架將為應用程序提供最佳性能。

          現(xiàn)在,讓我們看看用相同的C#代碼編寫此查詢的另一種方式:

          // A function to search for peoplePerson FindPerson(int id) {   var people = DbContext.GetPeople(); // Returns List
          return people.FirstOrDefault(x => x.ID == id);}
          // Then do thisvar person = FindPerson(123);

          請注意,null如果沒有找到匹配項,則返回第一個代碼。這段代碼也做同樣的事情。唯一的第一個代碼更糟糕的是它必須對集合本身執(zhí)行迭代。

          該本地變量return person;將允許程序返回控件,但是如果數(shù)據(jù)位于最后一個位置會發(fā)生什么呢?此數(shù)據(jù)搜索算法的復雜度仍為O(n)。

          避免unsafe上下文

          在您必須親自處理內(nèi)存時,C#還支持手動內(nèi)存管理。C#中的不安全上下文允許您操作內(nèi)存,執(zhí)行指針算術(shù),在可能無法訪問的內(nèi)存位置讀取和寫入數(shù)據(jù),等等。但是,.NET框架可以做很多事情來克服內(nèi)存問題,延遲和磁盤上其他問題。這也使.NET框架完全無需實際執(zhí)行任何內(nèi)存管理,.NET框架將為您做到這一點。

          使用不安全的上下文有很多好處,例如,當您要圍繞本機C ++庫編寫包裝器時。Emgu CV就是這樣一個示例,您將在其中編寫一些代碼來處理如何管理本機代碼,并以更簡單的方式來處理內(nèi)存中的錯誤。在這種情況下,您可以:

          1.使用指針管理和指針算術(shù)。您不能在此上下文之外的任何地址上執(zhí)行任何操作,這是.NET規(guī)則所處的位置。2.使用內(nèi)存管理來操作內(nèi)存中的對象。3.使用C ++風格的編程,這正是C#設(shè)計的目的。

          這幾乎沒有好處,如果您應該在應用程序中考慮這一點,請明智地考慮。

          關(guān)于Unsafe純屬個人觀點

          我還想指出,關(guān)于“不安全”的利弊,我所說的一切都是我個人的看法。我不經(jīng)常在程序中使用unsafe上下文,因為沒有理由考慮在應用程序中使用上下文。但是,如果您的應用程序需要本機內(nèi)存管理,則可以使用此上下文。

          盡可能使用Lambda表達式

          Lambda來自函數(shù)式編程領(lǐng)域,在C#中已廣泛使用,從內(nèi)聯(lián)函數(shù)一直到C#6中的getter only屬性。我將展示C#中的兩種用法,它們構(gòu)成的程序,不僅看起來更清爽,而且性能指標也更高。

          為此,我將向您顯示該C#代碼的IL。我個人喜歡在許多領(lǐng)域使用lambda,尤其是當我不得不用C#編寫內(nèi)聯(lián)函數(shù)時。自從可以使用此概念編寫僅用于getter的屬性以來,我一直在使用它們,并且我個人認為它比以前做同一件事的方法更好。

          1.將Lambda用于內(nèi)聯(lián)函數(shù)

          您應該知道一些C#編程的示例,使用這種寫法的代碼很多。

          例如在應用程序中進行事件處理的情況下,對于事件處理,您可以像下面這樣編寫當前函數(shù):


          // Without lamdbasmyBtn.Click += Btn_Click;
          public void Btn_Click (object sender, EventArgs e) { // Code to handle the event}
          // With the help of lambdasmyBtn.Click += (sender, e) => { // Code to handle the event. }

          請注意,編譯器將自動將對象映射到其類型。這在許多方面都很方便,因為它允許您用C#編寫僅與對象一起保留的內(nèi)聯(lián)函數(shù),除非您也想在其他任何地方使用它們。但是,這種處理事件的方法有一個缺點:一旦附加了事件處理程序,便無法刪除它。在C#中可以,-+。

          但是由于我們沒有刪除事件的參考,因此只能使用單獨的函數(shù)。但是,如果不必刪除處理程序,則應始終考慮在程序中使用這種事件處理方式。

          2.將Lambda用于僅Getter的屬性

          在C#中,有一個使用屬性而不是字段的概念。您可以控制如何設(shè)置值以及如何從字段中捕獲值。將其視為Java編程語言的getter和setter方法的替代方法(或類似方法)。唯一的區(qū)別是您不必在某個地方分別編寫它們,它們直接寫在字段本身的前面。然后,C#程序編譯器將創(chuàng)建自己的后備字段,用于存儲值。

          基本上,您必須編寫如下這樣的屬性:

          public string Name { get; }

          請注意,這些屬性是恒定的,設(shè)置后就無法更改。它們是在構(gòu)造函數(shù)中設(shè)置的,或者(從C#6開始)在它們的前面設(shè)置。像這樣:

          public string Name { get; } = "Afzaal Ahmad Zeeshan";

          但是,由于我們已經(jīng)知道這是一個常量字段,您不能修改它,那么為什么不創(chuàng)建一個簡單的常量屬性呢?事情變得有些棘手。甚至一個屬性也必須由字段來備份。在這種情況下,這將為我們解決問題:

          public string Name => "Afzaal Ahmad Zeeshan";

          這等效于編寫以下內(nèi)容:

          public string Name { get { return "Afzaal Ahmad Zeeshan"; } }

          但是由于編譯期將getter字段轉(zhuǎn)換為常量字段,并且在必須調(diào)用此屬性的時候才會在程序中使用該字段,因此性能要好得多。

          最后的話

          本指南系列的目的是使您了解一些使程序更易于閱讀和更好執(zhí)行的方法。C#編譯器本身會盡最大努力提高代碼的質(zhì)量和效率,而這程序員帶來便利,同時也將使程序更好地工作。

          除了上面提到的方法,還有許多其他提高可讀性的方法,其中許多方法適合公司團隊協(xié)作的形式編寫程序,因為大多數(shù)團隊往往都要求程序員遵循自己的編程方法和方式。

          往期精彩回顧




          【推薦】.NET Core開發(fā)實戰(zhàn)視頻課程?★★★

          .NET Core實戰(zhàn)項目之CMS 第一章 入門篇-開篇及總體規(guī)劃

          【.NET Core微服務實戰(zhàn)-統(tǒng)一身份認證】開篇及目錄索引

          Redis基本使用及百億數(shù)據(jù)量中的使用技巧分享(附視頻地址及觀看指南)

          .NET Core中的一個接口多種實現(xiàn)的依賴注入與動態(tài)選擇看這篇就夠了

          10個小技巧助您寫出高性能的ASP.NET Core代碼

          用abp vNext快速開發(fā)Quartz.NET定時任務管理界面

          在ASP.NET Core中創(chuàng)建基于Quartz.NET托管服務輕松實現(xiàn)作業(yè)調(diào)度

          現(xiàn)身說法:實際業(yè)務出發(fā)分析百億數(shù)據(jù)量下的多表查詢優(yōu)化

          關(guān)于C#異步編程你應該了解的幾點建議

          C#異步編程看這篇就夠了


          瀏覽 10
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  污污污网站在线看 | 亚洲无码视频免费 | 久久久久久欧美二区电影网 | 亚洲a视频在线 | 欧美大码一区二区免费看 |