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

作者:袖梨 2022-06-25

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

泛型1>=局部类型:

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

  ..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 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  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方法,类型参数之前有一个感叹号,这是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[] 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方法就可以用一个接口约束加以实现 where t : icomparable{}>;

基类约束:表是类型参数必须是继承子指定的类型

构造器约束:只支持无参的构造器约束,就是必须保障参数类型可以调用它的无参构造器

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

 

相关文章

精彩推荐