【51CTO独家特稿】本文的第一部分介绍没有文档记载的关键字,笔者保证这些C#关键字你肯定没有见到过,即使你去MSDN文档中找也没有,这些C#关键字也没有出现在Visual Studio的intellesence菜单中。
第二部分介绍有文档记载但不常用的C#关键字,或只不过是引入C#中的关键字,这些C#关键字在MSDN文档中是可以找到的。
我也为本文所涉及到的一些C#关键字制作了一些简单的例子,如果你有兴趣去测试,可以从http://www.codeproject.com/KB/Blogs/38695/UncommonTestSample.zip下载源代码。
无文档记载的C#关键字
1、__arglist
__arglist用于向一个函数发送一个参数,我们向函数发送参数的常规做法是在函数头指定一个参数列表,如果要向函数追加一个新参数,需要函数重载才行,如果要发送多个参数,可以使用参数数组。
那么我们为什么要使用__arglist呢?上面任何一种传递参数的方法都存在如下问题:
A) 如果我们使用函数重载,我们不得不为新增加的参数设计新的函数。
B) 如果我们使用参数数组,那参数类型必须相同,或者需要参数数组对象。
但__arglist不需要这么复杂,可以传递任何数量的参数给函数,可以是任何的类型,让我们看一段代码:
- public int paramLength(__arglist)
- {
- ArgIterator iterator = new ArgIterator(__arglist);
- return iterator.GetRemainingCount();
- }
下面我调用这个函数:
- int x = this.paramLength(__arglist(49,34,54,6,"Manimoy")); // returns 5
变量x将返回5,因为我们发送了5个参数给函数,我们可以使用下面的方法访问每一个函数:
- TypedReference tf = iterator.GetNextArg();
- TypedReference.ToObject(tf)
每调用一次GetNextArg,GetRemainingCount就会减少1,直到每个对象设置的迭代次数用完。
2、__refvalue
__refvalue从一个引用对象匹配值,可以使用它从TypedReference对象中获得真实的对象,它需要两个参数,一个是TypedReference对象,一个是要转换的类型,看下面的代码:
- int tfValue = __refvalue(tf, int);
执行后tfValue将被分配tf指向的整数值。
3、__makeref
__makeref可以从对象自身中提取出TypedReference对象,它和__refvalue刚刚相反,来看下面的代码:
- string name = "Ayan";
- TypedReference tf = __makeref(name);
4、__reftype
__reftype用于从TypedReference获取Type对象,看下面的代码你就知道怎么回事了:
- Type t = __reftype(tf);
- if(t.ToString().equals("System.String"))
- string str = __refvalue(t,string);
注意:虽然我在所有C#版本中都发现了这些关键字,但我并没有将它们用于生产环境,我不能保证这些关键字在今后的版本是否会仍然存在,使用风险一切由你自行承担。
有文档记载但用得很少的C#关键字
在这一部分我们将见到一些有文档记载但在编程中很少用到的关键字。
1、Yield
Yield是.Net 2.0中引入的一个关键字,用于产生以IEnumerable形式返回的语句,产生IEnumerable的块叫做迭代块。在下面的代码中,我创建了一列名单,返回长度小于5的名单,直到长度大于12时跳转到yield break语句。
- List lst = new List();
- lst.Add("Abhishek");
- lst.Add("Abhijit");
- lst.Add("Manimoy");
- lst.Add("Raj");
- lst.Add("Ayan");
- lst.Add("MacMillanRojer");
- lst.Add("Rizzuto");
- foreach (string x in lst)
- {
- if (x.Length > 12) // Breaks on MacMillanRojer
- yield break;
- else if (x.Length > 5) // Only returns those which are having length >5
- yield return x;
- else continue;
- }
实际上yield return x会评估每个元素,并创建所有符合条件(长度小于5)元素的enumerable,break语句将会终止循环,返回现有的Enumerable。
2、Fixed
Fixed只能用于Unsafe C#代码块,Fixed语句设置指针到一个固定的内存地址,因此被固定到内存中,即使垃圾回收线程也拿它没办法,来看下面的代码:
- int[] a = new int[] { 1, 2, 3 };
- fixed (int* pt = a)
- {
- int* c = pt;
- MessageBox.Show("Value : " + *c);
- // This will fix the variable totally so that it will
- // not be moved when Garbage collector is invoked.
- }
在这里指针c分配的位置的pt相同。它真正会对正常的垃圾回收进程产生限制,因此如果不需要最好不要使用它。
3、Checked / Unchecked
Checked用于控制算法溢出,当一个算术运算溢出了必需的大小时,Checked关键字会抛出一个StackOverflowException异常。看下面的代码:
- int x = int.MaxValue;
- int y = int.MaxValue;
- int z = checked(x + y);
当调用x+y时上面的语句抛出StackOverflowException异常,checked用于检查算术运算溢出,并抛出相应的异常,当StackOverflowException发生时z被赋予值0。
当我们不需要抛出异常时可以使用unchecked关键字。
- int x = int.MaxValue;
- int y = int.MaxValue;
- int z = unchecked(x + y);
执行上面的代码z将被赋予值-2。
4、Volatile
Volatile关键字用于定义不调用lock语句跨多线程修改的变量,Volatile变量不接受编译器优化,因此我们将得到变量最新的值,看下面的例子:
- public volatile int i;
- Thread th = new Thread(new ThreadStart(VolatileInvoke));
- th.Start();
- Thread.Sleep(5000); //Holds current Thread for 5 seconds.
- MessageBox.Show("Value of i : " + i);
- th.Abort();
- private void VolatileInvoke()
- {
- while (true)
- {
- i++;
- }
- }
线程启动后值将按1递增,直到被主线程取消。
注意:Volatile类型不具有线程优化。
5、StackAlloc
它也使用unsafe C#代码从堆栈中动态分配内存,stackalloc用于快速获得大内存,我们可以声明一个数组:
- int* array = stackalloc new int[1000]
当这个语句被调用时内存就分配好了。
不常见的C#关键字小结
关键字就介绍到这里,我只是为大家简单地做了介绍和举例,详细的使用还得靠你自己去琢磨,有什么想法请发表你的意见。
原文:UnCommon C# keywords - A Look
作者:Abhishek Sur
【编辑推荐】