.net 泛型 局部类型、属性访问器保护级别、命名空间别名限定符

.net 泛型 局部类型、属性访问器保护级别、命名空间别名限定符

泛型1>=局部类型:

  c#1.0中,一个类只可以放在一个文件中。c#2.0中用了一个关键字<partial>把一个类分成两个部分<即一个类的实现可以在多个文件中>。编译结果和写在一个文件中完全相同,更多的意义在于工程化的管理。

  ..1>>局部类型值适用与接口、类或者结构中,不支持枚举<一般也没这么大的枚举吧>;

  ..2>>同一个类型的各个部分必须都有修饰符partial,必须位于相同的命名空间中,必须同时编译、访问修饰符必须维持一致性;

  ..3>>关键字partial 是一个上下文关键字,只有和class、struct、interface放在一起时才有关键字的含义;

  ..4>>局部类型上的特性和接口具有“累加”效应;

  ..5>>如果一个类型有一个部分使用了abstract修饰符,那么整个类将被视为抽象类;

  ..6>>如果一个类型有一个部分使用了sealed修饰符,那么整个类将被视为密封类;

  ..7>>各部分不能使用相互矛盾的修饰符,比如不能在一个部分上使用abstract,又在另一个部分上使用sealed;

  ..8>>各部分上指定的基类必须一致。某些部分可以不指定基类,但如果指定,则必须相同。

  2>=属性访问器保护级别:

  c# 2.0允许对一个属性的get和set访问器使用不同的访问级别修饰符<注意属性访问器和属性的概念>。

  ..1>>属性访问器(get或set)上的访问修饰符必须比属性的访问修饰符更严格;
  ..2>>只能在一个属性访问器(get或set)上指定 访问修饰符,另一个默认使用属性的访问修饰符;
  ..3>>对于接口中的属性只能默认为public,不能设置属性访问器(get或set)的访问修饰符。

  3>=命名空间别名限定符<::>:

  c#2.0允许使用命名空间别名限定符(::)来避免不同命名空间中类型名称冲突的问题。当使用命名空间别名限定符(::)时编译器可以确保这是一个只适用于“命名空间别名”的限定符<查看il代码中使用的就是'::'>,不会辨析为其他类型、或者成员限定符(.)。关键字global可以放在命名空间别名限定符(::)的左边,它使得编译器只去搜索那些所有的命名空间,而不会去搜索其他的类型、或者成员。尽可能地使用命名空间别名限定符(::),而减少使用点号(.)这样的通用限定符<加快编译器搜索类型,编译后无任何区别>。

1>=泛型概述:

泛型是一种类型的多态;比如当我们写一个栈或者队列的时候,需要指定其数据类型,int一份代码,string一份代码,object的一份代码,这些代码除了数据类型不同之外其他大部分都是相同的,根据设计模式的思想,抽象出来变化点封装它,共同的部分作为共用的代码。这里的变化点就是类型了,共同部分就是算法相同,所以就把类型抽象化,于是乎泛型问世<个人理解>。

c#泛型由clr在运行时支持,这使得泛型可以在clr支持的各种语言上无缝集合;c#泛型代码在被编译<第一次编译>为il代码和元数据时【泛型版的il和元数据】,采用特殊的占位符来表示泛型类型,并用专有的il指令支持泛型操作,真正的泛型实例化工作发生在jit编译<第二次编译>时。当jit编译器第一次遇到这种特殊的il和元数据时,会利用实际的类型进行替换<泛型类型的实例化>。clr为所有类型参数是“引用类型”的泛型类型产生同一份代码,而对值类型来说,不同的值类型产生不同的代码,相同的则共用同一份代码。

c#泛型类型携带有丰富的元数据,因此c#的泛型类型可以应用于强大的反射技术;采用“基类, 接口, 构造器, 值类型/引用类型”的约束方式来实现对类型参数的 “显式约束”,提高了类型的安全性。

源代码:

mytype 1 public class mytype<t> where t : struct{
2     private t[] _items;
3     public void add(t itme)
4     {
5     }
6 }

编译后il如下:

il  1 //泛型类<'1代表元数或者参数数量>
 2  .class public auto ansi beforefieldinit mytype`1<valuetype .ctor
 3  //注意这里加上了泛型约束<[mscorlib]system.valuetype) t>
 4  //表明类型参数是值类型的
 5  ([mscorlib]system.valuetype) t>
 6        extends [mscorlib]system.object
 7 {
 8 } // end of class mytype`1
 9  //这是那个私有字段
10  .field private !t[] _items
11
12 //add方法,类型参数<t>之前有一个感叹号<!>,这是cil开始支持泛型
13 //后引入的新特性,它指出为类指定的第一个类型参数的存在,表明这是
14 //一个类型参数
15 .method public hidebysig instance void  add(!t itme) cil managed
16 {
17   // 代码大小       2 (0x2)
18   .maxstack  8
19   il_0000:  nop
20   il_0001:  ret
21 } // end of method mytype`1::add

 

 

 

除了这些区别外,泛型类和非泛型类的cil代码并无太大区别。

2>=泛型类型和泛型方法:

可以用于泛型的类型有类、接口,结构、委托。

c#支持泛型方法,但不支持除方法外的其他成员<属性、事件、索引器、构造器、析构器>;泛型方法可以包含在泛型类型中,也可以包含在非泛型类型中<即普通的类型>。

genericsmehod  1 public class genericsmehod
 2 {
 3     //非泛型类中的泛型方法,参数约束为引用类型
 4     //<传入值类型参数将引起编译错误>
 5     public int finditem<t>(t[] items, t item)where t:class
 6     {
 7         for (int i = 0; i < items.length; i++)
 8         {
 9             if (items[i].equals(item))
10             {
11                 return i;
12             }
13         }
14         return -1;
15     }
16 }

 

 

 

调用就不写了,泛型方法支持重载,但是之区别类型参数约束的重载是非法的;也是支持重写的,重写时的类型参数的约束被默认继承,任何的约束的指定都是不必要的,也是不可以指定约束的。

3>=泛型约束:

为什么要有约束呢?假如我写了一个泛型类,这个泛型参数调用到compareto方法,但是并不是所有的类型参数都有这个方法,假如传入的类型没这个方法,就会引起错误了,所以保证你的代码的健壮的话,加上约束还是很有必要的<就是说传入的类型必须有这个方法才可以编译通过,把错误暴露在编译阶段>。泛型约束支持四种形式的约束【接口约束,基类约束,构造器约束,值类型/引用类型约束】;约束并不是必须的,如果没有指定约束,那么类型参数将只能访问system.object类型中的公有方法。语法where语句

上面的类型参数需要一个compareto方法就可以用一个接口约束加以实现<public class mygenerics<t> where t : icomparable{}>;

基类约束:表是类型参数必须是继承子指定的类型<where t : 基类>;

构造器约束:只支持无参的构造器约束,就是必须保障参数类型可以调用它的无参构造器<where t : new()>:

值类型/引用类型约束:只有两种情况了<where t:struct>或者<where t:class>,指定参数类型必须是值类型或者引用类型

 

时间: 2024-11-01 09:58:42

.net 泛型 局部类型、属性访问器保护级别、命名空间别名限定符的相关文章

属性访问器-关于private set的疑问

问题描述 关于private set的疑问 属性访问器里面,private set和set究竟在使用过程中有什么区别?搞不明白为何要声明set为private,那为何get不声明为private呢?新手困惑,求指导. 解决方案 设置了 private,则类外部无法访问,只有内部可以访问. get 没有设置 private,则说明此属性可以类外部进行 get. 即在类外部,类似于一个只读的东东:只能 get,不能 set. set 与 get 的访问权限设置是独立的,相互不影响. 解决方案二: g

浅谈JavaScript 数据属性和访问器属性_javascript技巧

在JavaScript中对象被定义为"无序属性的集合,其属性可以包含基本值.对象或函数."通俗点讲,我们可以把对象理解为一组一组的名值对,其中值可以是数据或函数. 创建自定义对象通常有两种方法,第一种就是创建一个Object的实例,然后再为其添加属性和方法,例如: var person = new Object(); person.name = "Scott"; person.age = 24; person.sayName = function(){ alert(

JavaScript--数据属性和访问器属性

  在JavaScript中最基本的创建一个对象的方法是new一个Object()的实例,然后再为其添加属性与方法,下例创建一个包含属性name的person对象,name属性的特征值为"xiaochang": var person = new Object();person.name = "xiaochang";person.say = function(){ console.log("Hi, my name is " + this.name)

浅谈Javascript数据属性与访问器属性_javascript技巧

ES5中对象的属性可以分为'数据属性'和'访问器属性'两种. 数据属性一般用于存储数据数值,访问器属性对应的是set/get操作,不能直接存储数据值. 数据属性特性:value.writable.enumerable.configurable. 解释:configurable:true/false,是否可以通过delete删除属性,能否修改属性的特性,能否把属性修改为访问器属性,默认false: enumerable:true/false,是否可以通过for in循环返回,默认false: wr

无法显式调用运算符或访问器 无法对属性或索引器赋值

问题描述 无法显式调用运算符或访问器 无法对属性或索引器赋值 困扰了好久了.c#反汇编回来的程序报了2个错误, this.msc.add_Error(new DScriptControlSource_ErrorEventHandler(OnError)); this.msc.add_Timeout(new DScriptControlSource_TimeoutEventHandler(OnTimeout)); 提示:"MSScriptControl.DScriptControlSource_E

方法A无法实现类型B的接口访问器C,请使用显式接口实现

问题描述 publicoverridevoidremove_WillMove1(Handler1A_1)//此处remove_WillMove1报错方法"ADODB.EventProvider.remove_WillMove1(ADODB.Handler1)"无法实现类型"ADODB.EventProvider"的接口访问器"ADODB.Event.WillMove.remove".请使用显式接口实现.{} publicdelegatevoidH

《.NET程序员面试秘笈》----面试题4 举例说明属性、get和set访问器的使用

面试题4 举例说明属性.get和set访问器的使用 .NET程序员面试秘笈[考点]对属性(Property)的理解,C#中get和set访问器的编写方法,理解自动实现的属性. [出现频率] [解答] 本例通过属性操作类中声明的私有字段_username,请注意在Name属性的get和set访问器中的逻辑操作.本例还有一个自动实现的属性,可读取用户输入的数据.在ch01目录下新建一个程序文件,并命名为GetSet.cs,编写代码如程序1.5所示. 在命令行下编译GetSet.cs后,执行GetSe

Whidbey 初体验之局部类型 ( partial 类型)

Whidbey 初体验 之 局部类型 ( partial 类型) Visual Studio 2005 [Whidbey] 抢先体验版 [Express Beta 1 ] 出来有一段时间了,并且在微软的官方网站上有免费的下载(下载地址:http://lab.msdn.microsoft.com/vs2005/).就本人而言是非常喜欢c#这一新生的语言的.也许并不能说它是新生的,它是对以往各种语言的提炼,或许它是站在巨人的肩膀上的,所以才显得如此的优秀.伴随体验版而来的c# 2.0 给我们带来了新

asp.net HttpRequest 类型属性成员列表

HttpRequest 类型公开了以下成员. 构造函数 名称 说明 HttpRequest 基础结构.初始化 HttpRequest 对象. 页首 方法 名称 说明 BinaryRead 执行对当前输入流进行指定字节数的二进制读取. Equals 确定指定的 Object 是否等于当前的 Object. (继承自 Object.) Finalize 允许 Object 在"垃圾回收"回收 Object 之前尝试释放资源并执行其他清理操作. (继承自 Object.) GetHashCo