編寫高質量代碼的30條黃金守則-Day 01(首選隱式類型轉換)

編寫高質量代碼的30條黃金守則-Day 01(首選隱式類型轉換),本文由比特飛原創發佈,轉載務必在文章開頭附帶連接:https://www.byteflying.com/archives/6455數據庫

該系列文章由比特飛原創發佈,計劃用三個月時間寫徹底30篇文章,爲你們提供編寫高質量代碼的通常準則。網絡

一、概述

隱式類型轉換是微軟爲了 C# 支持匿名類型而加入的,使用 var 一般可使代碼的可讀性更強,甚至是幫咱們解決一些嚴重的性能問題。爲了清楚的明白 var 的做用機制,咱們首先來看看編譯器爲 var 作了哪些工做?性能

二、編譯器爲var關鍵字作了什麼?

首先 var 爲語法糖,編譯器在編譯時根據右值推斷出表達式類型,再由編譯器將推斷出的表達式類型寫入到 IL 中,因此以下2段代碼在 IL 中徹底一致。spa

string foo = "SomeString";
var foo = "SomeString";

編譯期間,編譯器根據右值 「SomeString」 ,能夠推斷出這個表達式(右值)的類型爲 string 類型,因而將 var 替換爲 string ,再將它寫到IL中,因而以上兩段初始化 foo 的代碼結果徹底一致。.net

咱們再來看一下兩段代碼的IL:cdn

編寫高質量代碼的30條黃金守則-Day 01(首選隱式類型轉換)

本文示例的源代碼對象

DnSpy 的反編譯結果blog

編寫高質量代碼的30條黃金守則-Day 01(首選隱式類型轉換)

Microsoft 技術支持文檔中 ldstr 的解釋資源

注意:string 也是語法糖,編譯時,string 被替換爲 System.String 寫進IL。開發

因而咱們獲得了一個重要的結論:

var 爲語法糖,在編譯期間就已經被編譯器所決定,開發人員沒法爲編譯器決定類型。

隱式類型轉換爲上述代碼帶來了良好的可讀性,任何一名開發人員都會知道第2行代碼的 var 的類型,它讓咱們更加的關注代碼片斷中咱們所須要關注的部分,而不是把重點放在它的類型上。由於大多數時候,這都是沒有意義的。

三、隱式類型轉換所帶來的良好可讀性

爲了明白良好可讀性的問題,咱們先來看一個代碼片斷:

var foo = new SomeType();

以上代碼清晰明瞭,對於維護代碼的人來講,它沒有增長任何的理解成本,foo 的類型就是 SomeType 類型。不少優秀開源項目中的大量被使用的工廠模式,也提供了相似的方法,以下代碼片斷:

var huaWei = PhoneFactory.CreatePhone();

一個簡單的靜態工廠類 PhoneFactory ,公開了 CreatePhone 方法,閱讀這段代碼的開發人員,在幾乎沒有增長理解成本的狀況下,很清楚的知道 huaWei 表明手機工廠類所生產的一個手機對象。可是下面的代碼,狀況可能就稍有不一樣了:

var result = someObject.DoSomething(someParameter);

你沒法輕鬆的知道 result 的類型和它所表達的意義,事實上,它的不良好的可讀性,表如今如下幾個方面:

一、在此處,result 這個變量名並非最好的選擇;

二、someObject 的含義不明;

三、DoSomething 含糊不清;

四、沒法明確的知道 someParameter 代碼什麼。

若是換成如下代碼,狀況會好不少:

var mostPopularPhone = someObject.DoSomething(someParameter);

狀況有所好轉,意思也更清楚。結合語義上下文,var 的類型不言自明。可是在這種狀況下,我依然建議你們將代碼改成如下形式:

Phone mostPopularPhone = someObject.DoSomething(someParameter);

這被我寫在以前所在公司的開發手冊上,我相信個人經驗必定是正確的。

讓咱們再來看一個新的示例:

var score = GetSomeNumber();

var rate = score / 100;

rate 的類型由變量 score 決定,而後開發者沒法一眼看出 score 的類型,因此這是一個不良好的可讀性的代碼片斷,咱們應該改成:

var score = GetSomeNumber();

double rate = score / 100;

怎麼樣,是否是看到這樣的代碼,內心舒服多了?由於你的理解成本更低了,心情舒暢了,一會兒搬磚都能搬到5樓了。

因而,咱們有了兩點總結:

一、當含義明確,在代碼上下文較爲清楚時(簡單的變量定義或工廠方法),建議優先使用 var;

二、在其它複雜狀況下,儘可能直接寫出 var 的類型。

隱式類型轉換所帶來的絕非僅僅是良好的可讀性,它有時可能會幫咱們消除一些難以發現的Bug,這又是怎麼回事呢?

四、隱式類型轉換幫咱們解決嚴重的性能問題

人自覺得本身是世界上最聰明的生物,事實上並不是如此,有時候,編譯器比咱們聰明得多,也可靠得多。

咱們看看如下兩個代碼片斷:

public IEnumerable<string> GetPhoneStartsWith1(string prefix) {
    IEnumerable<string> phones =
                    from r in db.Phones
                    select r.PhoneName;

    var result = phones.Where(r => r.StartsWith(prefix));
    return result;
}
 
public IEnumerable<string> GetPhoneStartsWith2(string prefix) {
    var phones =
        from r in db.Phones
        select r.PhoneName;

    var result = phones.Where(r => r.StartsWith(prefix));
    return result;
}

以上兩段代碼有何不一樣?GetPhoneStartsWith1 方法中的 phones 原先的返回類型應當爲 IQueryable<string>,但在這裏被顯式聲明的 phones 的 IEnumerable<string> 強制轉換了,熟悉 EF 的朋友們必定知道,IQueryable<T> 爲延遲加載,自己並不會馬上查詢數據庫,事實上它只生成了一個表達式樹,在最終須要使用數據的時候纔會真正執行查詢動做。

因而 GetPhoneStartsWith1 方法將數據庫中的可能的全部數據所有取回本地,再由 var result = phones.Where(r => r.StartsWith(prefix)); 執行本地過濾,消耗了太多網絡資源,而且使用了 .Net 的數據過濾機制。

GetPhoneStartsWith2 方法則否則,phones 的類型被編譯器推斷爲 IQueryable<string> ,並不會所以執行查詢操做,真正的查詢動做由 var result = phones.Where(r => r.StartsWith(prefix)); 執行,也就是說,它的數據過濾動做由數據庫引擎負責運算,最終只將符合條件的數據發送回本地,既節省了網絡傳遞成本,又節省了運算成本,豈不是一箭雙鵰?

五、總結

  1. 當含義明確,在代碼上下文較爲清楚時(簡單的變量定義或工廠方法),建議優先使用 var;
  2. 在其它複雜狀況下,儘可能直接寫出 var 的類型;
  3. 儘量地相信編譯器,大多數時候,它比咱們優秀得多。

開發人員應牢記以上開發守則,不然,人民羣衆會仇恨你,你的朋友和家人也會嘲笑你,唾棄你

該系列文章由比特飛原創發佈,計劃用三個月時間寫徹底30篇文章,爲你們提供編寫高質量代碼的通常準則。

本文由 比特飛 原創發佈,歡迎你們踊躍轉載。

轉載請註明本文地址:https://www.byteflying.com/archives/6455

相關文章
相關標籤/搜索