近來在小組C#快速成長團隊 討論了若干話題,有些感覺不錯,特總結與大家分享。
當然,所謂話題,重點在於進行討論,是否是最佳實踐也屬於大家的個人之見。以下觀點若有差錯,盡情蹂躏。
1:String str1 = “str1”+ 9; 和String str2 = “str2”+ 9.ToString(); 哪個效率高
可以知道“str1”+ 9,在運行時會完成一次裝箱行為。9.ToString(),沒有發生裝箱行為,Int類型的ToString()方法的實際原型為:
public override String ToString() { return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);}可能有人會問,那是不是原型中的Number.FormatInt32方法會發生裝箱行為呢?實際Number.FormatInt32方法是一個非托管的方法,原型如下:
[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]public static extern string FormatInt32(int value, string format, NumberFormatInfo info);
它通過直接操作內存來進行int到string的轉換,效率要比裝箱高很多。
所以,答案是:後者
裝箱為什麼會帶來性能損耗,因為它內部發生了太多事情:
1:首先,為值類型在托管堆中分配內存。內存總量除了值類型本身所分配的內存外,還要加上類型對象指針和同步塊索引;
2:值類型的值復制到新分配的堆內存;
3:返回已經成為引用類型的對象的地址;
2:as,is轉型比強制轉型的優勢
優勢在於as,is 不拋出異常,如果轉型失敗,則返回null
強制轉型則會拋出異常,導致代碼必須處理異常,效率低。
值得注意的是,as只能轉型基本類型,對於基本類別如int等的轉型,只能使用強制轉型或is。
3:readonly和const的區別或者說哪個更好
1:const天然就是static的,所以不能用static修飾;readonly無此限制;
2:const只能修飾基元類型;readonly無此限制;
3:const是編譯期常量;readonly為運行期常量,其初始值除了在初始化器還可以在類型的構造函數中設定;
4:const經編譯後,以實際值代替了變量(可查看IL驗證),效率顯然要高一些,可用到關鍵算法中,除此之外,與readonly比沒有任何優勢。
4:初始化器和構造器的異同
初始化器實際是語法糖,經編譯後,它在構造函數的最開始執行。也就是說,初始化器可以理解為構造函數的一部分。
5:枚舉在使用中的注意事項
1:如果不指定枚舉的零值,會帶來什麼問題;
static Week week;static void Main(string[] args){Console.WriteLine(week);}
即使未給week賦值,也會打印出零值。
2:如果為枚舉中的元素指定了相同的值,又會帶來什麼問題。
會導致相等型比較的時候出現與預期不符的結果
3:建議不給枚舉顯式指定值,但是如果枚舉用於位運算則要為其元素指定2的指數冪值。
6:為什麼LINQ語句都要開始於from而不是select
顯而易見的原因是為了智能感知,要讓他在輸入LINQ查詢的時候起作用,from子句就必須在最前面;如:
var AllCustomers = from Customer in db.Customers
select new { Customer.ContactName, Customer.Country };
7:dynamic可以用它來簡化反射。
使用反射,調用方代碼:
DynamicSample dynamicSample = new DynamicSample();var addMethod = typeof(DynamicSample).GetMethod("Add");int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 });
在使用dynamic後,我們的代碼看上去更簡潔了,並且在可控的范圍內減少了一次拆箱的機會:
dynamic dynamicSample2 = new DynamicSample();int re2 = dynamicSample2.Add(1, 2);
8:foreach不能替代for的原因
1: 首先,對集合的每次增刪操作(是不是全部集合?不得而知,但是起碼是絕大部分集合),都會讓集合的version字段+1,foreach采用的是迭代器模式,每次迭代的時候都要判斷version是不是保持一致,如果不一致,則拋出異常。而for沒有這方面的限制。所以,采用
List<int> list = new List<int>() { 0, 1, 2, 3 };foreach (int item in list){list.Remove(item);Console.WriteLine(item.ToString());}
會拋出異常,而改為for則不會。這是for不能被foreach取代叼的最重要原因。
2:foreach默認調用集合的迭代器的Dispose方法,如果該迭代器繼承了IDispose方法的話。
9:區別IComparable<T>和IComparer<T>
前者IComparable<T>為類提供默認的比較器,而IComparer<T>可以為集合類提供更多的比較器。具體查看html">:
http://www.BkJia.com/kf/201104/88259.html
10:LINQ和比較器及迭代器優缺點比較
要進行排序和比較,傳統的方式,存在兩個問題:
1:可擴展性太低,如果存在新的排序要求,就得實現新的比較器;
2:對代碼的侵入性太高,為類型繼承了接口,增加了新的方法;
可參見博文的討論
http://www.BkJia.com/kf/201104/88258.html
在我們自己的代碼中強烈建議你利用LINQ帶來便捷性,但我們仍需掌握比較器、迭代器、索引器的原理,以便我們更好地理解LINQ的思想,寫出更加高質量的代碼。