首页 > 编程语言 >18个不常见的C#关键字,您使用过几个?

18个不常见的C#关键字,您使用过几个?

时间:2023-05-21 16:32:23浏览次数:35  
标签:__ 变量 关键字 C# 18 System int 我们

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



其实,yield return x 将判断每个元素,并创建了满足条件所有的元素的enumerable(length>5)。

1  List <</span>string> lst = new List<</span>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

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变量不受编译器优化,因此我们将获得该变量的所有的时间最新的值。见下面的例子:



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

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类型没有线程优化。


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语句来定义一个类引用。例如我写:usingAbhishek=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 <</span>T>()
2 {
3      return default(T);
4 }

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


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


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

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


1  int ?  nullableint =  null ;

这里nullableint将被赋值null。


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


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


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


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


结论:


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



标签:__,变量,关键字,C#,18,System,int,我们
From: https://blog.51cto.com/u_13675550/6319686

相关文章

  • 对$nextTick的理解,及其实现原理
    1.对$nextTick的理解:VUE中数据变化后,是异步更新DOM的,如果想数据变化后,操作dom,这个时候获取到的是没有变化的值eg:<divclass="msg">{{msg}}</div>mounted(){this.msg='我是测试文字'console.log(document.querySelector('.msg'......
  • Docker 启动 [email protected] 并使用 Navicat 客户端连接
    docker运行mysql镜像dockerrun--namesome-mysql-p3306:3306-eMYSQL_ROOT_PASSWORD=my-secret-pw-dmysql:5.7其中some-mysql是您要分配给容器的名称my-secret-pw是要为MySQLroot用户设置的密码-p将容器的3306端口发布到主机的端口3306-e设置容器的环境......
  • CF1774F Magician and Pigs【性质】
    有一个空序列,需要维护如下三个操作:1x:在序列中添加\(x\)。2x:把序列中每个元素的值减去\(x\)。3:重复从第一条到本条操作的前一条的所有操作,包括操作\(3\)。当一个数的值\(\leq0\)时,它将被移出序列。求最后有多少个数还在序列中。答案对\(998244353\)取模。\(n\leq......
  • NOIP2018普及组试题题解
    1.标题统计原题:https://www.luogu.com.cn/problem/P5015#include<bits/stdc++.h>#definelllonglongusingnamespacestd;strings;intans=0;intmain(){ getline(cin,s);intlen=s.length(); for(inti=0;i<len;i++){ if(s[i]>='0'&&......
  • requests: 基本使用、get、post、代理、cookie案例、超级鹰打码api
    1、requests_1_基本使用""".-''-..--._..._.'.-.)|__|......
  • 计算机网络--Ch6.应用层(一)
    一.网络应用模型1.应用层概述应用层对应用程序的通信提供服务。应用层协议定义:应用进程交换的报文类型,请求还是响应?各种报文类型的语法,如报文中的各个字段及其详细描述。字段的语义,即包含在字段中的信息的含义。进程何时、如何发送报文,以及对报文进行响应的规则。1.1客户/服务......
  • c语言
    C语言是一种高级程序设计语言,由贝尔实验室的DennisRitchie在20世纪70年代初开发而成。它是一种通用性强、效率高、功能丰富的编程语言,被广泛应用于计算机科学和软件工程领域。C语言的特点之一是它具有较高的可移植性。这意味着开发人员可以在不同的操作系统和硬件平台上编写相同的......
  • Stack Overflow 2017 开发者调查报告(程序员必看)
    最近,StackOverflow发布了一篇2017开发者调查报告,此次在全球有超过64,000名开发者参与调查,分别对其技能、工具、学习趋势等数据进行了统计,比较遗憾的是中国参与调查的开发者很少,只有大概300人左右,所以有些调查结果可能跟中国环境不太相符,不过毫无疑问,这几乎代表了全球技术的......
  • 人生苦短,请用 Chrome!
    今年举办的WWDC大会上,苹果可是各种指名道姓地踩竞争对手来拔高自己,这种下三滥的营销手段换做是别人并不稀奇,但是这可是伟大神圣的苹果啊,有点不适应。其中大会上放出了这么一幅图,想必大家都看到过:我看到这张图的第一印象是:卧槽,好牛逼!但是,我怎么有点不信呢。虽说我相信苹果不太可能......
  • 吐血推荐珍藏的 Chrome 插件二
    了解我的人知道,我一直是Chrome的死忠粉,Chrome那丰富的插件可能是我这么钟爱Chrome的原因之一,我在去年的时候写过一篇文章,推荐了一些我常用的Chrome插件给大家,很多读者是因为那篇文章从此也爱上了Chrome,那么时隔一年多的时间,今天再给大家更新一些很棒的Chrome插件。1.Lis......