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

歡迎訪問 生活随笔!

生活随笔

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

C#

c#语言规范所在文件夹,C#规范整理·语言要素

發布時間:2025/3/15 C# 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c#语言规范所在文件夹,C#规范整理·语言要素 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如有不理解,請留言,開始!

1. 正確操作字符串

拼接字符串一定要考慮使用 StringBuilder ,默認長度為16,實際看情況設置。

StringBuilder本質: 是以非托管方式分配內存。

同時StringFormat方法 內部也是使用StringBuilder進行字符串格式化。

2. 使用默認轉型方法

類型的轉換運算符 :每個類型內部都有一個方法(運算符),分為隱式轉換和顯示轉換。

自己實現隱式轉換:

puclic static implicit operator Ip(string ip)

{

Ip iptemp=new Ip(ip);

return iptemp;

}

使用類型內置的Parse、TryParse、 ToString、ToDouble、 ToDateTime

使用幫助類提供的方法: System.Convert類、 System.BitConverter類來進行類型的轉換。

使用CLR支持的類型:父類和子類之間的轉換。

3. 區別對待強制轉型與as和is

為了編譯更強壯的代碼,建議更常使用as和is

什么時候使用as

如果類型之間都上溯到了某個共同的基類,那么根據此基類進行的轉型(即基類轉型為子類本身)應該使用as。子類與子類之間的轉型,則應該提供轉換操作符,以便進行強制轉型。

as操作符永遠不會拋出異常,如果類型不匹配(被轉換對象的運行時類型既不是所轉換的目標類型,也不是其派生類型),或者轉型的源對象為null,那么轉型之后的值也為null。

什么時候使用is

as操作符有一個問題,即它不能操作基元類型。如果涉及基元類型的算法,就需要通過is轉型前的類型來進行判斷,以避免轉型失敗。

4.TryParse比Parse好

這個肯定好,不說了。安全

5.使用int?來確保值類型也可以為null

基元類型為什么需要為null?考慮兩個場景:

數據庫支持整數可為空

數據在傳輸過程中存在丟失問題,導致傳過來的值為null

寫法: int?i=null;

語法T?是Nullable<T>的簡寫,兩者可以相互轉換。可以為null的類型表示其基礎值類型正常范圍內的值再加上一個null值。例如,Nullable<Int32>,其值的范圍為-2 147 483 648~2 147 483 647,再加上一個null值。

?經常和??配合使用,比如:

Copyint?i=123;

int j=i??0;

6.區別readonly和const的使用方法

使用const的理由只有一個,那就是效率。之所以說const變量的效率高,是因為經過編譯器編譯后,我們在代碼中引用const變量的地方會用const變量所對應的實際值來代替。比如: const=100, const和100被使用的時候是等價,const自帶static光圈。

const和readonly的本質區別如下:

const是編譯期常量,readonly是運行期常量

const只能修飾基元類型、枚舉類型或字符串類型,readonly沒有限制。

注意:在構造方法內,可以多次對readonly賦值。即在初始化的時候。

7.將0值作為枚舉的默認值

允許使用的枚舉類型有byte、sbyte、short、ushort、int、uint、long和ulong。應該始終將0值作為枚舉類型的默認值。不過,這樣做不是因為允許使用的枚舉類型在聲明時的默認值是0值,而是有工程上的意義。

既然枚舉類型從0開始,這樣可以避免一個星期多出來一個0值。

8.避免給枚舉類型的元素提供顯式的值

不要給枚舉設定值。有時候有某些增加的需要,會為枚舉添加元素,在這個時候,就像我們為枚舉增加元素ValueTemp一樣,極有可能會一不小心增加一個無效值。

9.習慣重載運算符

比如:Salary familyIncome=mikeIncome+roseIncome; 閱讀一目了然。通過使用opera-tor關鍵字定義靜態成員函數來重載運算符,讓開發人員可以像使用內置基元類型一樣使用該類型。

10.創建對象時需要考慮是否實現比較器

有特殊需要比較的時候就考慮。集合排序比較通過linq 也可以解決。

11.區別對待==和Equals

無論是操作符“==”還是方法“Equals”,都傾向于表達這樣一個原則:

對于值類型,如果類型的值相等,就應該返回True。

對于引用類型,如果類型指向同一個對象,則返回True。

注意

由于操作符“==”和“Equals”方法從語法實現上來說,都可以被重載為表示“值相等性”和“引用相等性”。所以,為了明確有一種方法肯定比較的是“引用相等性”,FCL中提供了Object.ReferenceEquals方法。該方法比較的是:兩個示例是否是同一個示例。

對于string這樣一個特殊的引用類型,微軟覺得它的現實意義更接近于值類型,所以,在FCL中,string的比較被重載為針對“類型的值”的比較,而不是針對“引用本身”的比較。

12.重寫Equals時也要重寫GetHashCode

除非考慮到自定義類型會被用作基于散列的集合的鍵值;否則,不建議重寫Equals方法,因為這會帶來一系列的問題。

集合找到值的時候本質上是先去 查找HashCode,然后才查找該對象來比較Equals

注意

重寫Equals方法的同時,也應該實現一個類型安全的接口IEquatable<T>,比如 :class Person:IEquatable

13.為類型輸出格式化字符串

有兩種方法可以為類型提供格式化的字符串輸出。

一種是意識到類型會產生格式化字符串輸出,于是讓類型繼承接口IFormattable。這對類型來說,是一種主動實現的方式,要求開發者可以預見類型在格式化方面的要求。

更多的時候,類型的使用者需為類型自定義格式化器,這就是第二種方法,也是最靈活多變的方法,可以根據需求的變化為類型提供多個格式化器。

一個典型的格式化器應該繼承接口IFormatProvider和ICustomFomatter

14.正確實現淺拷貝和深拷貝

淺拷貝

將對象中的所有字段復制到新的對象(副本)中。其中,值類型字段的值被復制到副本中后,在副本中的修改不會影響到源對象對應的值。而引用類型的字段被復制到副本中的是引用類型的引用,而不是引用的對象,在副本中對引用類型的字段值做修改會影響到源對象本身。

深拷貝

同樣,將對象中的所有字段復制到新的對象中。不過,無論是對象的值類型字段,還是引用類型字段,都會被重新創建并賦值,對于副本的修改,不會影響到源對象本身。

無論是淺拷貝還是深拷貝,微軟都建議用類型繼承IClone-able接口的方式明確告訴調用者:該類型可以被拷貝。當然,ICloneable接口只提供了一個聲明為Clone的方法,我們可以根據需求在Clone方法內實現淺拷貝或深拷貝。

一個簡單的淺拷貝的實現代碼如下所示:

Copyclass Employee:ICloneable

{

public string IDCode {get;set;}

public int Age {get;set; }

public Department Department{get;set;}

#region ICloneable成員

public object Clone()

{

return this.MemberwiseClone();

}

#endregion

}

class Department

{

public string Name {get;set;}

public override string ToString()

{

return this.Name;

}

}

注意到Employee的IDCode屬性是string類型。理論上string類型是引用類型,但是由于該引用類型的特殊性(無論是實現還是語義),Object.MemberwiseClone方法仍舊為其創建了副本。也就是說,在淺拷貝過程,我們應該將字符串看成是值類型。

一個簡單的深拷貝實現樣例如下(建議使用序列化的形式來進行深拷貝)

Copyclass Employee:ICloneable

{

public string IDCode{get;set;}

public int Age{get;set;}

public Department Department{get;set;}

#region ICloneable成員

public object Clone()

{

using(Stream objectStream=new MemoryStream())

{

IFormatter formatter=new BinaryFormatter();

formatter.Serialize(objectStream,this);

objectStream.Seek(0,SeekOrigin.Begin);

return formatter.Deserialize(objectStream)as Employee;

}

}

#endregion}

同時實現深拷貝和淺拷貝

由于接口ICloneable只有一個模棱兩可的Clone方法,所以,如果要在一個類中同時實現深拷貝和淺拷貝,只能由我們自己實現兩個額外的方法,聲明為DeepClone和Shallow。Em-ployee的最終版本看起來應該像如下的形式:

Copy[Serializable]

class Employee:ICloneable

{

public string IDCode{get;set;}

public int Age{get;set;}

public Department Department{get;set;}

#region ICloneable成員

public object Clone()

{

return this.MemberwiseClone();

}

#endregion

public Employee DeepClone()

{

using(Stream objectStream=new MemoryStream())

{

IFormatter formatter=new BinaryFormatter();

formatter.Serialize(objectStream,this);

objectStream.Seek(0,SeekOrigin.Begin);

return formatter.Deserialize(objectStream)as Employee;

}

}

public Employee ShallowClone()

{

return Clone()as Employee;

}}

14.利用dynamic來簡化反射實現

dynamic是Framework 4.0的新特性。dynamic的出現讓C#具有了弱語言類型的特性。編譯器在編譯的時候不再對類型進行檢查,編譯器默認dynamic對象支持開發者想要的任何特性。

比如,即使你對GetDynamicObject方法返回的對象一無所知,也可以像如下這樣進行代碼的調用,編譯器不會報錯:

Copydynamic dynamicObject=GetDynamicObject();

Console.WriteLine(dynamicObject.Name);

Console.WriteLine(dynamicObject.SampleMethod());

當然,如果運行時dynamicObject不包含指定的這些特性(如上文中帶返回值的方法SampleMethod),運行時程序會拋出一個RuntimeBinderException異常:“System.Dynamic.ExpandoObject”未包含“Sam-pleMethod”的定義。

var與dynamic有巨大的區別

var是編譯器的語法糖

dynamic是運行時解析,在編譯期時,編譯器不對其做任何檢查。

反射使用

不使用dynamic方式

CopyDynamicSample dynamicSample=new DynamicSample();

var addMethod=typeof(DynamicSample).GetMethod("Add");

int re=(int)addMethod.Invoke(dynamicSample,new object[] {1,2});

使用dynamic方式

Copydynamic dynamicSample2=new DynamicSample();

int re2=dynamicSample2.Add(1,2);

建議:始終使用dynamic來簡化反射實現。

總結

在大部分應用情況下,“效率”并沒有那么高的地位,靈活性更重要。在部分情況下,“靈活性”并沒有那么高的地位,效率最重要。

總結

以上是生活随笔為你收集整理的c#语言规范所在文件夹,C#规范整理·语言要素的全部內容,希望文章能夠幫你解決所遇到的問題。

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