目录

1. ObsoleteAttribute
2. 设置默认值属性: DefaultValueAttribute
3. DebuggerBrowsableAttribute
4. ??运算符
5. Curry 及 Partial 方法
6. WeakReference
7. Lazy
8. BigInteger
9. 非官方关键字:__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 方法…

1. ObsoleteAttribute

ObsoleteAttribute: 可适用于除程序集、模块、参数或返回值以外的所有程序元素。将元素标记为 Obsolete 可实现通知用户的功能,表明该元素在产品之后的新版本中会被移除。

Message属性包含一个字符串,可获取变通方法消息,是对可选程序元素的说明。

IsError属性:是Bool 类型,如果将值设为“True”,则编译器会将使用已过时的程序元素视为错误。

1:publicstaticclassObsoleteExample

2:{

3://MarkOrderDetailTotalAsObsolete.

4:[ObsoleteAttribute("Thisproperty(DepricatedOrderDetailTotal)isobsolete.UseInvoiceTotalinstead.",false)]

5:publicstaticdecimalOrderDetailTotal

6:{

7:get

8:{

9:return12m;

10:}

11:}

12:

13:publicstaticdecimalInvoiceTotal

14:{

15:get

16:{

17:return25m;

18:}

19:}

20:

21://MarkCalculateOrderDetailTotalAsObsolete.

22:[ObsoleteAttribute("Thismethodisobsolete.CallCalculateInvoiceTotalinstead.",true)]

23:publicstaticdecimalCalculateOrderDetailTotal()

24:{

25:return0m;

26:}

27:

28:publicstaticdecimalCalculateInvoiceTotal()

29:{

30:return1m;

31:}

32:}

如果运行程序,编译器就会报错以及Warning。

1:Console.WriteLine(ObsoleteExample.OrderDetailTotal);

2:Console.WriteLine();

3:Console.WriteLine(ObsoleteExample.CalculateOrderDetailTotal());

2. 通过“DefaultValueAttribute”属性可设置缺省值

DefaultValueAttribute 指定属性的默认值。可以使用任何值创建 DefaultValueAttribute。成员的默认值通常是其初始值。可视化设计器可以使用默认值重置成员的值。代码生成器也可使用默认值确定是否为成员生成代码,但是必须在成员函数中设置初始值。

1:publicclassDefaultValueAttributeTest

2:{

3:publicDefaultValueAttributeTest()

4:{

5://UsetheDefaultValuepropetyofeachpropertytoactuallysetit,viareflection.

6:foreach(PropertyDescriptorpropinTypeDescriptor.GetProperties(this))

7:{

8:DefaultValueAttributeattr=(DefaultValueAttribute)prop.Attributes[typeof(DefaultValueAttribute)];

9:if(attr!=null)

10:{

11:prop.SetValue(this,attr.Value);

12:}

13:}

14:}

15:

16:[DefaultValue(25)]

17:publicintAge{get;set;}

18:

19:[DefaultValue("Anton")]

20:publicstringFirstName{get;set;}

21:

22:[DefaultValue("Angelov")]

23:publicstringLastName{get;set;}

24:

25:publicoverridestringToString()

26:{

27:returnstring.Format("{0}{1}is{2}.",this.FirstName,this.LastName,this.Age);

28:}

29:}

3. DebuggerBrowsableAttribute

表示成员是否在Debugger 变量窗口显示以及如何显示。

1:publicstaticclassDebuggerBrowsableTest

2:{

3:privatestaticstringsquirrelFirstNameName;

4:privatestaticstringsquirrelLastNameName;

5:

6://ThefollowingDebuggerBrowsableAttributepreventsthepropertyfollowingit

7://fromappearinginthedebugwindowfortheclass.

8:[DebuggerBrowsable(DebuggerBrowsableState.Never)]

9:publicstaticstringSquirrelFirstNameName

10:{

11:get

12:{

13:returnsquirrelFirstNameName;

14:}

15:set

16:{

17:squirrelFirstNameName=value;

18:}

19:}

20:

21:[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]

22:publicstaticstringSquirrelLastNameName

23:{

24:get

25:{

26:returnsquirrelLastNameName;

27:}

28:set

29:{

30:squirrelLastNameName=value;

31:}

32:}

33:}

逐步调试程序时,就会发现代码会一直在执行:

1:DebuggerBrowsableTest.SquirrelFirstNameName="Hammy";

2:DebuggerBrowsableTest.SquirrelLastNameName="Ammy";4. ??操作符

?? 运算符称作 null 合并运算符。如果此运算符的左操作数不为 null,则此运算符将返回左操作数;否则返回右操作数,如果在尝试将可以为null 值的类型分配给不可以为null值的类型时,没有使用??运算符,则会生成编译时的错误。如果使用强制转换,且当前未定义可以为 null 值的类型,则会引发 InvalidOperationException 异常。

1:int?x=null;

2:inty=x??-1;

3:Console.WriteLine("ynowequals-1becausexwasnull=>{0}",y);

4:inti=DefaultValueOperatorTest.GetNullableInt()??default(int);

5:Console.WriteLine("iequalsnow0becauseGetNullableInt()returnednull=>{0}",i);

6:strings=DefaultValueOperatorTest.GetStringValue();

7:Console.WriteLine("Returns'Unspecified'becausesisnull=>{0}",s??"Unspecified");5. Curry 及 Partial 方法

Curry 方法是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。

1:publicstaticclassCurryMethodExtensions

2:{

3:publicstaticFunc<A,Func<B,Func<C,R>>>Curry<A,B,C,R>(thisFunc<A,B,C,R>f)

4:{

5:returna=>b=>c=>f(a,b,c);

6:}

7:}

如果无法确定成员函数的返回类型可使用Var执行。

Partial—Partial类型允许我们将一个类、接口或结构分成好几个部分,分别实现在几个不同的.cs文件中。关键字partial是一个上下文关键字,只有和class、struct、interface放在一起时才有关键字的含义。因此partial的引入不会影响现有代码中名称为partial的变量


1:publicstaticclassCurryMethodExtensions

2:{

3:publicstaticFunc<C,R>Partial<A,B,C,R>(thisFunc<A,B,C,R>f,Aa,Bb)

4:{

5:returnc=>f(a,b,c);

6:}

7:}6. WeakReference

Weak Reference 表示类型化弱引用,即在引用对象的同时仍然允许垃圾回收来回收该对象。如果你想使用该引用,可以设置为强引用类型,保证该对象不被回收。

1:WeakReferenceTesthugeObject=newWeakReferenceTest();

2:hugeObject.SharkFirstName="Sharky";

3:WeakReferencew=newWeakReference(hugeObject);

4:hugeObject=null;

5:GC.Collect();

6:Console.WriteLine((w.TargetasWeakReferenceTest).SharkFirstName);7. Lazy<T>

Lazy<T>提供对延迟一些大资源或资源紧张的对象的初始化的支持。在程序的生存期内,特别是在这种方式创建或执行可能不发生使用延迟初始化延迟一种或大量占用资源的对象的创建、资源的任务的执行。

1:publicabstractclassThreadSafeLazyBaseSingleton<T>

2:whereT:new()

3:{

4:privatestaticreadonlyLazy<T>lazy=newLazy<T>(()=>newT());

5:

6:publicstaticTInstance

7:{

8:get

9:{

10:returnlazy.Value;

11:}

12:}

13:}

8. BigIntegerBigInteger 类型 表示任意大的带符号整数。理论上来讲,该类型的数据是没有边界值限制的。该类型与其他整型类型不同,包含MinValue和MaxValue 属性。

1:stringpositiveString="91389681247993671255432112000000";

2:stringnegativeString="-90315837410896312071002088037140000";

3:BigIntegerposBigInt=0;

4:BigIntegernegBigInt=0;

5:

6:posBigInt=BigInteger.Parse(positiveString);

7:Console.WriteLine(posBigInt);

8:negBigInt=BigInteger.Parse(negativeString);

9:Console.WriteLine(negBigInt);

9. 未官方记录的 C# 关键字: __arglist __reftype __makeref __refvalue

第9条奖的关键字官方文档并没有记录,可能正在测试中。然而这些关键字丰富了Visual Studio 编辑器的功能,也能被识别。

开发人员可以使用__makeref关键字创建变量。使用__refvalue修饰变量可以从 TypedReference中获得变量值。__arglist关键字与params的作用相同,可以访问参数列表。

1:inti=21;

2:TypedReferencetr=__makeref(i);

3:Typet=__reftype(tr);

4:Console.WriteLine(t.ToString());

5:intrv=__refvalue(tr,int);

6:Console.WriteLine(rv);

7:ArglistTest.DisplayNumbersOnConsole(__arglist(1,2,3,5,6));

为了使用__arglist, 需要定义ArglistTest 类

1:publicstaticclassArglistTest

2:{

3:publicstaticvoidDisplayNumbersOnConsole(__arglist)

4:{

5:ArgIteratorai=newArgIterator(__arglist);

6:while(ai.GetRemainingCount()>0)

7:{

8:TypedReferencetr=ai.GetNextArg();

9:Console.WriteLine(TypedReference.ToObject(tr));

10:}

11:}

12:}



10. Environment.NewLine

获取为此环境定义的换行字符串。

1:Console.WriteLine("NewLine:{0}firstline{0}secondline{0}thirdline",Environment.NewLine);11. ExceptionDispatchInfo

表示捕获特定点的异常情况。可以使用ExceptionDispatchInfo.Throw 方法,命名空间为System.Runtime.ExceptionServices。

1:ExceptionDispatchInfopossibleException=null;

2:

3:try

4:{

5:int.Parse("a");

6:}

7:catch(FormatExceptionex)

8:{

9:possibleException=ExceptionDispatchInfo.Capture(ex);

10:}

11:

12:if(possibleException!=null)

13:{

14:possibleException.Throw();

15:}

12. Environment.FailFast()

如果想退出程序,且不需要调用任何Finally 块或Finalizers,可以使用FailFast。

1:strings=Console.ReadLine();

2:try

3:{

4:inti=int.Parse(s);

5:if(i==42)Environment.FailFast("Specialnumberentered");

6:}

7:finally

8:{

9:Console.WriteLine("Programcomplete.");

10:}

13. Debug.Assert & Debug.WriteIf & Debug.Indent

Debug.Assert——检查条件;如果条件为false,则显示一个消息框,其中会显示调用堆栈。Debug.Assert尽在调试版中有效,在发布版中如果要执行断言,则使用Trace.Assert。

Debug.Assert(1==0,"Thenumbersarenotequal!Ohmygod!");


如果Assert在Debug模式下失败,则会显示下图:

14. Parallel.For & Parallel.Foreach

多线程的情况下较为常用。

Parallel.For—执行循环,迭代可以运行。

1:int[]nums=Enumerable.Range(0,1000000).ToArray();

2:longtotal=0;

3:

4://Usetypeparametertomakesubtotalalong,notanint

5:Parallel.For<long>(0,nums.Length,()=>0,(j,loop,subtotal)=>

6:{

7:subtotal+=nums[j];

8:returnsubtotal;

9:},

10:(x)=>Interlocked.Add(reftotal,x)

11:);

12:

13:Console.WriteLine("Thetotalis{0:N0}",total);

Interlocked.Add 方法将两个整型值相加,并将结果保存到第一个数值,可以作为原子操作。

Parallel.Foreach——执行 foreach(在 Visual Basic 中为 For Each)操作,其中在 Partitioner 上可能会并行运行迭代。

15. IsInfinity

判断数值的正负情况。

Console.WriteLine(,Double.IsInfinity(3.0/0)?:);原文链接:http://www.codeproject.com/Articles/1021335/Top-Underutilized-Features-of-NET