转自:http://www.cnblogs.com/zhuqil/archive/2010/04/09/UnCommon-Csharp-keywords-A-Look.html

1、__arglist

让我们先从__arglist开始。 __arglist是用来给方法传送参数。通常我们是通过函数头部指定的参数列表给方法传递参数的。如果我们想要给方法传递一组新的参数,我们需要重载方法。如果我们想要传递的参数数量不确定,我们需要使用param数组。我们为什么要使用__arglist,因为上面两种方法,存在的下面问题:

a、如果我们使用方法重载,一旦要传递一组新的参数,我们都要增加一个新的函数重载。

b、如果我们用param数组,参数类型必须相同或者使用param对象数组。

__arglist能解决上面的问题。你可以传递任何参数给函数,可以是任何类型,我们可以使用简单的步骤分析每个参数。

让我们先看下下面代码:

1 public int paramLength(__arglist)
2 {
3           ArgIterator iterator = new ArgIterator(__arglist);
4           return iterator.GetRemainingCount();
5 }

如果我使用下面代码调用该函数

1 int x = this.paramLength(__arglist(49,34,54,6,"Manimoy")); // returns 5 

将被返回5给变量x。这是因为我们给这个方法传递了5个参数。我们可以访问每个参数,如:

1 TypedReference tf = iterator.GetNextArg();
2 TypedReference.ToObject(tf)

每次调用GetNextArg,GetRemainingCount将减1,直到遍历完迭代器的每个对象。

2、__refvalue

另一个有趣的关键字是__refvalue。它是用来获取一个引用对象的的值。你可以用来从TypedReference对象中获得实际对象。这需要两个参数,第一个就是TypedReference对象和另一个是转换的类型。看看下面代码:

1 int tfValue = __refvalue(tf, int); 

3、__makeref

__makeref将使从对象中找出TypedReference对象。这跟_refvalue刚刚相反。请看下面的代码:

1 string name = "Ayan";
2 TypedReference tf = __makeref(name);

4、 __reftype

__reftype是用来从TypedReference类型的对象获得类型。看下面代码所示:

1 Type t = __reftype(tf);
2 if(t.ToString().equals("System.String"))
3 string str = __refvalue(t,string); 

注:虽然我在所有的C#版本中发现上面这些关键字,但我没在工作中使用它。在未来版本的C#可能不存在这些关键字,所以是否使用看你自己的风险。

5、Yield

Yield出现在.NET 2.0中,使用Yield将以枚举数对象值的形式返回,yield 语句只能出现在iterator 块中,该块可用作方法、运算符或访问器的体。在以下代码中,我构建了一个名字列表,将返回长度小于5的名字列表,遇到yield break语句返回。


 1 List<string> lst = new List<string>();
 2 lst.Add("Abhishek");
 3 lst.Add("Abhijit");
 4 lst.Add("Manimoy");
 5 lst.Add("Raj");
 6 lst.Add("Ayan");
 7 lst.Add("MacMillanRojer");
 8 lst.Add("Rizzuto");
 9 foreach (string x in lst)
10 {
11    if (x.Length > 12) // Breaks on MacMillanRojer
12      yield break;
13    else if (x.Length > 5) // Only returns those which are having length >5
14      yield return x;
15    else continue;
16 }
17  

其实,yield return x 将判断每个元素,并创建了满足条件所有的元素的enumerable(length> 5)。
break语句将终止循环,并返回现有创建好的枚举。

6、 Fixed

另一种不常见的关键字是Fixed,它只能在不安全的C#代码块中使用。Fixed语句在个固定的内存地址设置一个指针,它不会被移动到任何地方,即使执行了垃圾收集线程。让我们来看看下面的代码:


1  int[] a = new int[] { 1, 2, 3 };
2 fixed (int* pt = a)
3 {
4    int* c = pt;
5    MessageBox.Show("Value : " + *c);
6    // This will fix the variable totally so that it will
7    // not be moved when Garbage collector is invoked. 
8 }

在这里,指针c和pt被分配相同的位置。Fixed通常会花销一些资源。实际上它妨碍垃圾收集的正常进程。因此,实际中应该避免使用 fixed语句。

7、Checked / Unchecked

另一个名为checked的关键字是用来控制算术溢出的情况。当算术运算溢出时,Checked关键字抛出OverflowException异常。

看下这段代码:

1 int x = int.MaxValue;
2 int y = int.MaxValue;
3 int z = checked(x + y);  

上述声明中,当执行到x + y时,将抛出OverflowException异常。 checked用来检查运算溢出并引发相应的异常。 当发生OverflowException异常时,z被赋值为0。

当我们不需要抛出异常时,我们可以使用关键字unchecked。

1 int x = int.MaxValue;
2 int y = int.MaxValue;
3 int z = unchecked(x + y);

通过执行上面的代码,z的值将被赋值为-2。

8、Volatile

volatile关键字用于定义一个变量,这个变量跨多个线程修改而不被lock(虽然我们大部分的时间锁定它们)。 volatile变量不受编译器优化,因此我们将获得该变量的所有的时间最新的值。见下面的例子:


 1 public volatile int i;
 2 Thread th = new Thread(new ThreadStart(VolatileInvoke));
 3 th.Start();
 4 Thread.Sleep(5000); //Holds current Thread for 5 seconds.
 5 MessageBox.Show("Value of i : " + i);
 6 th.Abort();
 7 
 8 private void VolatileInvoke()
 9 {
10    while (true)
11    {
12          i++;
13    }
14 } 

线程启动,volatile整数的值增加1,直到它被主线程中止。

注意:Volatile类型没有线程优化。

9、StackAlloc

在unsafe的C#代码中使用,动态从堆栈分配内存。stackalloc用于快速获取内存。当我们使用堆栈,我们可以利用内存快速存取的优势。我们可以这样声明一个数组:

1 int* array = stackalloc new int[1000]  

注意:您应该始终牢记,stackalloc内存是非常有限的。它是由每个线程默认为1MB。因此,如果我们需要大量的内存(超过1MB),我们必须回到原来堆内存结构。

10、 Global ::

当想要用本地的命名空间隐藏的全局的命名空间,这个关键字是非常方便的。假设我们有我们的项目中创建了一个名为System的类,C#中是允许这样做的。当我想使用全局的System空间时,我们必须使用global::.。让我们来看看下面的例子:


 1 internal class System
 2 {
 3         internal class Array :IEnumerable 
 4         {
 5             public int Length
 6             {
 7                 get{return 1000}
 8             }
 9             #region IEnumerable Members
10             public IEnumerator GetEnumerator()
11             {
12                 Debug.Write("This is Dummy Array");
13                 return base.GetEnumerator();
14             }
15 
16             #endregion
17         }
18 }

现在,如果你要调用System.Array它会调用一个本地定义。要调用全局的System,我们需要使用global::System。当你确定调用全局命名空间时,最好它始终使用global:: 。

11、Namespace/Class别名

我们使用using 来定义别名。有2种形式的别名:

a、Namespace别名:

当你想缩短比较长的命名空间时,可以使用命名空间的别名。


1 using Abhishek = System.Drawing;
2 public class X 
3 {
4      public X()
5      {
6         Abhishek.Graphics g = this.CreateGraphics();
7      }
8 }  

在这里,我们为System.Drawing的定义了一个别名Abhishek 。因此,我们在代码中引用Abhishek,与引用System.Drawing是相同的。

b、Class别名:
您也可以使用using语句来定义一个类引用。例如我写:using Abhishek=System.Drawing.Bitmap;

Abhisek等同于Bitmap类。我们可以创建Abhishe的对象,直接访问静态函数。


1 using Abhishek=System.Drawing.Graphics;
2 public class X
3 {
4      public X()
5      {
6             Abhishek g = this.CreateGraphics();
7      }
8 }

因此,Abhishek将对应本机的Graphics对象而不是整个命名空间的。

12、extern别名

我们使用C#工作,大多数时候需要引用外部控件集。

我们会遇到这样的情况,在相同的应用程序中相同命名空间中添加两个版本的dll时。在这种情况下,我们需要外部别名功能,来指定两个不同的程序集。

例如:

假设我们添加一个程序集x10.dll(V1),其中有一Y类

我们添加x20.dll(V2),我们可能要使用Y类

首先,要参考完全合格的程序集,我们需要在命令行中声明一个别名。

/r:XV1=X10.dll

/r:XV2=X20.dll

现在参考我们的使用

1 extern alias XV1;
2 extern alias XV2;

13、??

??与null值一起使用。在2.0中引入。看以下内容:

1 MyClass x = null;
2 x = x ?? new MyClass();

??的意思是说,如果X是null 值,将new MyClass() ,否则将赋值现有的X值

14、@variables

通常是C#不允许使用关键字做变量的。但是有一种方式例外。我们可以通过使用@创建与关键字具有相同的名称的变量。

假设我们定义:

1 int @int = 10;

这意味着声明了一个名字为int的变量和并分配10给它。

15、Readonly

目前,readonly是C#关键字,用来创建不能被程序修改的变量。该声明为readonly的变量,变量的值将被分配一次,它将在整个对象执行过程中保持相同的值。

声明一个只读变量:

1 public readonly int readonlyvariable = 20; 

声明了一个值为20 的变量。再对这个变量赋值是不允许的。

16 、Const & readonly 的区别?

readonly类似关键字const。唯一不同的是, const 变量在编译时定义的,readonly变量在运行时定义。您可以从内部构造函数中分配readonly变量的值,因此根据你的构造函数分配,readonly值可能不同。

1 public readonly int readsecond;
2 public Documented()
3 {
4       readsecond = DateTime.Now.Second;
5 } 

在这里,readsecond将根据对象的初始化指派不同的值,对于const这是不可能的。

17 、Default

对于一般对象,关键字default非常方便。当对象未初始化,它返回的默认值。例如,如果没有赋予任何值,我们都知道整数被初始化为0。当没有赋任何值,字符串为空字符。当不指定任何值,对象为null。

这些值是根据default关键字分配。
因此,如果我们写:

1 int x = default(int);//will be assigned to 0

类似于:
int x;
一般情况下,当类型不确定时,我们可以使用default来分配特定的值给对象。让我们看看该示例:

1 public T GetDefault<T>()
2 {
3      return default(T);
4 } 

该函数返回每个类型的默认值。从而

因此,我们可以使用关键字default非常容易获取对象默认的分配的值。

1 int defx = this.GetDefault<int>(); //will assign 0
2 char defy = this.GetDefault<char>(); // will assign null('\0')
3 object defz = this.GetDefault<object>(); // will assign null

18、Nullable Types

C#的Nullable类型可以处理空值甚至是基本数据类型。每个nullable类型是来自System.Nullable。我们可以这样定义nullables:

1 int? nullableint = null; 

这里nullableint将被赋值null。

如果您访问nullable变量,您将获得2个属性。

HasValue属性将返回false,如果null被分配给变量;

Value属性返回变量的实际值。

您还可以使用每种nullable类型的对象的GetValueOrDefault函数来得到变量的默认值。

结论:

我的目的是给你一个简短方式介绍一下这些关键字的知识,以及如何去使用它们。请随意发表您的评论。

代码点击下载

PS:

1到4是Undocumented关键字,5到18是documented关键字。

如果觉得对你有点帮助,或者有点意思。请推荐一下,谢谢。

原文参考:UnCommon C# keywords - A Look

作者:朱祁林
出处:http://zhuqil.cnblogs.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

18个不常见的C#关键字,您使用过几个?的更多相关文章

  1. 简析--Java中常见的一些关键字的解析

    在Java开发中我们经常会用到一些关键字,关键字的定义很有意思"Java事先定义好的,具有特殊含义的单词",那么我们怎么来用好关键字呢?下面我们对一些常见的关键字进行分析和比较; ...

  2. c++中常见概念、关键字等的区别

    (1).重载,覆盖和隐藏的区别: 重载主要是函数的重载,函数名相同,返回类型相同,但是函数形参不同,被调用时,根据函数形参决定调用原函数还是重载函数. 覆盖主要用在继承多态中,函数前加virtual关 ...

  3. JAVA代码中最常见到的关键字表

    abstract 抽象类或方法 assert 用来查找内部程序错误 break 跳出一个switch或循环 byte 8 位整数类型 case switch的一个分支 catch 捕获异常的try块子 ...

  4. Ubuntu 18.04 LTS 常见问题解决 2

    1 每次重启后都有system program problem detected sudo gedit /etc/default/apport 然后将打开的文件中的enabled=1改为0,原因暂时不 ...

  5. 谈谈Javascript的this关键字(this is not this)

    前言: 看文章标题你就知道,这篇文章我只讲一个简单的Javascript的this关键字,说它简单——它又不简单,因为曾几何时我也对this关键字有些困惑,它也确实会让不少程序员感到不解——它像是一个 ...

  6. Android -- Annotation(注解)原理详解及常见框架应用

    1,我们在上一篇讲到了EventBus源码及3.0版本的简单使用,知道了我们3.0版本是使用注解方式标记事件响应方法的,这里我们就有一个疑问了,为什么在一个方法加上类似于"@Subscrib ...

  7. final关键字总结

    参考文章[https://www.cnblogs.com/xrq730/p/4820296.html] 前言:在Java中final作为最常见的一个关键字,平常用到的地方也很多,接下来就来看看什么是f ...

  8. Java多线程(三)—— synchronized关键字详解

    一.多线程的同步 1.为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源.必须对这种潜在资源冲突进行预防. 解决方法:在线程使用一个资源时为其加锁即可. 访问资 ...

  9. 如何在Ubuntu 18.04上安装和配置Apache 2 Web服务器(转)

    如何在Ubuntu 18.04上安装和配置Apache 2 Web服务器 什么是Apache Web Server? Apache或Apache HTTP服务器是一个免费的开源Web服务器,由Apac ...

随机推荐

  1. _mysql.c:29:20: error: Python.h: No such file or directory

    在Centos系统中安装 pip install MySQL-python 提示: _mysql.c:29:20: error: Python.h: No such file or directory ...

  2. SSM整合pom.xml和导包

    SSM 整合-自己写的 SSM Spring +SpringMVC+Mybatis 配置 及pom.xml SSM框架(spring+springMVC+Mybatis) pom.xml文件 mave ...

  3. 微信小程序——template的循环嵌套

    上一篇我们有写到 template的使用方法 .在实际运用中,需要做到template里面再嵌套一层循环.我们先看一下数据结构: 模板是用于循环list,现在的需求是在模板里面嵌套一个orderIte ...

  4. 多变量频率统计——r

    例如有X1,X2,..,Xn个变量,我需要对每一个变量进行频次统计,如果一个一个求解的话非常麻烦,如table(X1), table(X2), ... ,table(Xn).有没有简单的语句一次性求解 ...

  5. 安卓程序代写 网上程序代写[原]C语言基础

    C 作者:han1202012 发表于2013-11-1 19:53:29 原文链接 阅读:28 评论:0 查看评论

  6. Linux强制杀进程命令行工具

    需求, 有时候我们会有手动启动程序, 但是又在后台, 没有像服务那样有start, 和stop的程序, 这时候需要用强制杀进程方式 涉及工具, awk, sed, xargs, kill 需求一: 已 ...

  7. maven学习日记(三)-------开发环境搭建(springmvc+hibernate4)各种maven错误汇总

    1.maven编码 gbk 的不可映射字符 解决这个问题的思路: 在maven的编译插件中声明正确的字符集编码编码——编译使用的字符集编码与代码文件使用的字符集编码一致!! 安装系统之后,一般中文系统 ...

  8. 计算机网络——网络层

    一.虚拟线路与数据报线路 1. 在网络层提供有连接的计算机网络为虚电路网络: 如因特网:它需要VC(虚拟电路)号,用于建立虚拟电路的报文称为信令报文,相关的协议称为信令协议: 无连接的网络为数据报网络 ...

  9. e791. 为JSpinner定制编辑器

    This example replaces the default editor (a JFormattedTextField) in a spinner component with a custo ...

  10. LintCode #452 删除链表中的元素

    方法很笨拙,被链表给绕住了,抽空在整理一下. /** * Definition for ListNode * public class ListNode { * int val; * ListNode ...