目錄
1. ObsoleteAttribute
2. 設(shè)置默認(rèn)值屬性: DefaultValueAttribute
3. DebuggerBrowsableAttribute
4. ??運算符
5. Curry 及 Partial 方法
6. WeakReference
7. Lazy
8. BigInteger
9. 非官方關(guān)鍵字:__arglist __reftype __makeref __refvalue
10. Environment.NewLine
11. ExceptionDispatchInfo
12. Environment.FailFast
13. Debug.Assert, Debug.WriteIf 及 Debug.Indent
14. Parallel.For 及 Parallel.Foreach
15. IsInfinity方法
本文介紹了.Net 常被忽略,但卻非常有用戶的15個功能,包含ObsoleteAttribute,DefaultValueAttribute,DebuggerBrowsableAttribute,?運算符,Curry 及 Partial 方法…
ObsoleteAttribute: 可適用于除程序集、模塊、參數(shù)或返回值以外的所有程序元素。將元素標(biāo)記為 Obsolete 可實現(xiàn)通知用戶的功能,表明該元素在產(chǎn)品之后的新版本中會被移除。
Message屬性包含一個字符串,可獲取變通方法消息,是對可選程序元素的說明。
IsError屬性:是Bool 類型,如果將值設(shè)為“True”,則編譯器會將使用已過時的程序元素視為錯誤。
1: public static class ObsoleteExample 2: { 3: // Mark OrderDetailTotal As Obsolete. 4: [ObsoleteAttribute("This PRoperty (DepricatedOrderDetailTotal) is obsolete. Use InvoiceTotal instead.", false)] 5: public static decimal OrderDetailTotal 6: { 7: get 8: { 9: return 12m; 10: } 11: } 12: 13: public static decimal InvoiceTotal 14: { 15: get 16: { 17: return 25m; 18: } 19: } 20: 21: // Mark CalculateOrderDetailTotal As Obsolete. 22: [ObsoleteAttribute("This method is obsolete. Call CalculateInvoiceTotal instead.", true)] 23: public static decimal CalculateOrderDetailTotal() 24: { 25: return 0m; 26: } 27: 28: public static decimal CalculateInvoiceTotal() 29: { 30: return 1m; 31: } 32: }如果運行程序,編譯器就會報錯以及Warning。
1: Console.WriteLine(ObsoleteExample.OrderDetailTotal); 2: Console.WriteLine(); 3: Console.WriteLine(ObsoleteExample.CalculateOrderDetailTotal());
DefaultValueAttribute 指定屬性的默認(rèn)值??梢允褂萌魏沃祫?chuàng)建 DefaultValueAttribute。成員的默認(rèn)值通常是其初始值。可視化設(shè)計器可以使用默認(rèn)值重置成員的值。代碼生成器也可使用默認(rèn)值確定是否 為成員生成代碼,但是必須在成員函數(shù)中設(shè)置初始值。
1: public class DefaultValueAttributeTest 2: { 3: public DefaultValueAttributeTest() 4: { 5: // Use the DefaultValue propety of each property to actually set it, via reflection. 6: foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(this)) 7: { 8: DefaultValueAttribute attr = (DefaultValueAttribute)prop.Attributes[typeof(DefaultValueAttribute)]; 9: if (attr != null) 10: { 11: prop.SetValue(this, attr.Value); 12: } 13: } 14: } 15: 16: [DefaultValue(25)] 17: public int Age { get; set; } 18: 19: [DefaultValue("Anton")] 20: public string FirstName { get; set; } 21: 22: [DefaultValue("Angelov")] 23: public string LastName { get; set; } 24: 25: public override string ToString() 26: { 27: return string.Format("{0} {1} is {2}.", this.FirstName, this.LastName, this.Age); 28: } 29: }
表示成員是否在Debugger 變量窗口顯示以及如何顯示。
1: public static class DebuggerBrowsableTest 2: { 3: private static string squirrelFirstNameName; 4: private static string squirrelLastNameName; 5: 6: // The following DebuggerBrowsableAttribute prevents the property following it 7: // from appearing in the debug window for the class. 8: [DebuggerBrowsable(DebuggerBrowsableState.Never)] 9: public static string SquirrelFirstNameName 10: { 11: get 12: { 13: return squirrelFirstNameName; 14: } 15: set 16: { 17: squirrelFirstNameName = value; 18: } 19: } 20: 21: [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)] 22: public static string SquirrelLastNameName 23: { 24: get 25: { 26: return squirrelLastNameName; 27: } 28: set 29: { 30: squirrelLastNameName = value; 31: } 32: } 33: }逐步調(diào)試程序時,就會發(fā)現(xiàn)代碼會一直在執(zhí)行:
1: DebuggerBrowsableTest.SquirrelFirstNameName = "Hammy"; 2: DebuggerBrowsableTest.SquirrelLastNameName = "Ammy";?? 運算符稱作 null 合并運算符。如果此運算符的左操作數(shù)不為 null,則此運算符將返回左操作數(shù);否則返回右操作數(shù),如果在嘗試將可以為null 值的類型分配給不可以為null值的類型時,沒有使用??運算符,則會生成編譯時的錯誤。如果使用強制轉(zhuǎn)換,且當(dāng)前未定義可以為 null 值的類型,則會引發(fā) InvalidOperationException 異常。
1: int? x = null; 2: int y = x ?? -1; 3: Console.WriteLine("y now equals -1 because x was null => {0}", y); 4: int i = DefaultValueOperatorTest.GetNullableInt() ?? default(int); 5: Console.WriteLine("i equals now 0 because GetNullableInt() returned null => {0}", i); 6: string s = DefaultValueOperatorTest.GetStringValue(); 7: Console.WriteLine("Returns 'Unspecified' because s is null => {0}", s ?? "Unspecified");Curry 方法是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。
1: public static class CurryMethodExtensions 2: { 3: public static Func<A, Func<B, Func<C, R>>> Curry<A, B, C, R>(this Func<A, B, C, R> f) 4: { 5: return a => b => c => f(a, b, c); 6: } 7: }如果無法確定成員函數(shù)的返回類型可使用Var執(zhí)行。
Partial—Partial類型允許我們將一個類、接口或結(jié)構(gòu)分成好幾個部分,分別實現(xiàn)在幾個不同的.cs 文件中。關(guān)鍵字partial是一個上下文關(guān)鍵字,只有和class、struct、interface放在一起時才有關(guān)鍵字的含義。因此partial 的引入不會影響現(xiàn)有代碼中名稱為partial的變量。
1: public static class CurryMethodExtensions 2: { 3: public static Func<C, R> Partial<A, B, C, R>(this Func<A, B, C, R> f, A a, B b) 4: { 5: return c => f(a, b, c); 6: } 7: }Weak Reference 表示類型化弱引用,即在引用對象的同時仍然允許垃圾回收來回收該對象。如果你想使用該引用,可以設(shè)置為強引用類型,保證該對象不被回收。
1: WeakReferenceTest hugeObject = new WeakReferenceTest(); 2: hugeObject.SharkFirstName = "Sharky"; 3: WeakReference w = new WeakReference(hugeObject); 4: hugeObject = null; 5: GC.Collect(); 6: Console.WriteLine((w.Target as WeakReferenceTest).SharkFirstName);Lazy<T>提供對延遲一些大資源或資源緊張的對象的初始化的支持。在程序的生存期內(nèi),特別是在這種方式創(chuàng)建或執(zhí)行可能不發(fā)生使用延遲初始化延遲一種或大量占用資源的對象的創(chuàng)建、資源的任務(wù)的執(zhí)行。
1: public abstract class ThreadSafeLazyBaseSingleton<T> 2: where T : new() 3: { 4: private static readonly Lazy<T> lazy = new Lazy<T>(() => new T()); 5: 6: public static T Instance 7: { 8: get 9: { 10: return lazy.Value; 11: } 12: } 13: }
1: string positiveString = "91389681247993671255432112000000"; 2: string negativeString = "-90315837410896312071002088037140000"; 3: BigInteger posBigInt = 0; 4: BigInteger negBigInt = 0; 5: 6: posBigInt = BigInteger.Parse(positiveString); 7: Console.WriteLine(posBigInt); 8: negBigInt = BigInteger.Parse(negativeString); 9: Console.WriteLine(negBigInt);
第9條講 的關(guān)鍵字官方文檔并沒有記錄,可能正在測試中。然而這些關(guān)鍵字豐富了Visual Studio 編輯器的功能,也能被識別。
開發(fā)人員可以使用__makeref關(guān)鍵字創(chuàng)建變量。使用__refvalue修飾變量可以從 TypedReference中獲得變量值。__arglist關(guān)鍵字與params的作用相同,可以訪問參數(shù)列表。
1: int i = 21; 2: TypedReference tr = __makeref(i); 3: Type t = __reftype(tr); 4: Console.WriteLine(t.ToString()); 5: int rv = __refvalue( tr,int); 6: Console.WriteLine(rv); 7: ArglistTest.DisplayNumbersOnConsole(__arglist(1, 2, 3, 5, 6));
為了使用__arglist, 需要定義ArglistTest 類
1: public static class ArglistTest 2: { 3: public static void DisplayNumbersOnConsole(__arglist) 4: { 5: ArgIterator ai = new ArgIterator(__arglist); 6: while (ai.GetRemainingCount() > 0) 7: { 8: TypedReference tr = ai.GetNextArg(); 9: Console.WriteLine(TypedReference.ToObject(tr)); 10: } 11: } 12: }獲取為此環(huán)境定義的換行字符串。
1: Console.WriteLine("NewLine: {0} first line{0} second line{0} third line", Environment.NewLine);表示捕獲特定點的異常情況??梢允褂肊xceptionDispatchInfo.Throw 方法,命名空間為System.Runtime.ExceptionServices。
1: ExceptionDispatchInfo possibleException = null; 2: 3: try 4: { 5: int.Parse("a"); 6: } 7: catch (FormatException ex) 8: { 9: possibleException = ExceptionDispatchInfo.Capture(ex); 10: } 11: 12: if (possibleException != null) 13: { 14: possibleException.Throw(); 15: }
如果想退出程序,且不需要調(diào)用任何Finally 塊或Finalizers,可以使用FailFast。
1: string s = Console.ReadLine(); 2: try 3: { 4: int i = int.Parse(s); 5: if (i == 42) Environment.FailFast("Special number entered"); 6: } 7: finally 8: { 9: Console.WriteLine("Program complete."); 10: }
Debug.Assert——檢查條件;如果條件為 false,則顯示一個消息框,其中會顯示調(diào)用堆棧。Debug.Assert盡在調(diào)試版中有效,在發(fā)布版中如果要執(zhí)行斷言,則使用Trace.Assert。
Debug.Assert(1 == 0, "The numbers are not equal! Oh my god!");如果Assert在Debug模式下失敗,則會顯示下圖:

多線程的情況下較為常用。
Parallel.For—執(zhí)行循環(huán),迭代可以運行。
1: int[] nums = Enumerable.Range(0, 1000000).ToArray(); 2: long total = 0; 3: 4: // Use type parameter to make subtotal a long, not an int 5: Parallel.For<long>(0, nums.Length, () => 0, (j, loop, subtotal) => 6: { 7: subtotal += nums[j]; 8: return subtotal; 9: }, 10: (x) => Interlocked.Add(ref total, x) 11: ); 12: 13: Console.WriteLine("The total is {0:N0}", total);Interlocked.Add 方法將兩個整型值相加,并將結(jié)果保存到第一個數(shù)值,可以作為原子操作。
Parallel.Foreach——執(zhí)行 foreach(在 Visual Basic 中為 For Each)操作,其中在 Partitioner 上可能會并行運行迭代。

表示數(shù)值是無窮大情況。僅double和float類型數(shù)值除以0是產(chǎn)生。
1: Console.WriteLine("IsInfinity(3.0 / 0) == {0}.", Double.IsInfinity(3.0 / 0) ? "true" : "false");
原文鏈接:http://www.codeproject.com/Articles/1021335/Top-Underutilized-Features-of-NET新聞熱點
疑難解答