泛型(Generics)

泛型是CLR 2.0中引入的最重要的新特性,使得可以在类、方法中对使用的类型进行参数化。

例如,这里定义了一个泛型类:

class MyCollection<T> { T variable1; private void Add(T param){ } }

使用的时候:

MyCollection<string> list2 = new MyCollection<string>();

MyCollection<Object> list3 = new MyCollection<Object>();

泛型的好处

  • 编译时就可以保证类型安全
  • 不用做类型装换,获得一定的性能提升

泛型方法、泛型委托、泛型接口

除了泛型类之外,还有泛型方法、泛型委托、泛型接口:


//泛型委托

public static delegate T1 MyDelegate<T1, T2>(T2 item);

MyDelegate<Int32, String> MyFunc = new MyDelegate<Int32, String>(SomeMethd);

//泛型接口

public class MyClass<T1, T2, T3> : MyInteface<T1, T2, T3> { public T1 Method1(T2 param1, T3 param2) { throw new NotImplementedException(); } }

interface MyInteface<T1, T2, T3> { T1 Method1(T2 param1, T3 param2); }


//泛型方法

static void Swap<T>(ref T t1, ref T t2) { T temp = t1; t1 = t2; t2 = temp; }

String str1 = "a";

String str2 = "b";

Swap<String>(ref str1, ref str2);

泛型约束(constraints)
可以给泛型的类型参数上加约束,可以要求这些类型参数满足一定的条件

约束

说明

where T: struct 类型参数需是值类型
where T : class 类型参数需是引用类型
where T : new() 类型参数要有一个public的无参构造函数
where T : <base class name> 类型参数要派生自某个基类
where T : <interface name> 类型参数要实现了某个接口
where T : U 这里T和U都是类型参数,T必须是或者派生自U

这些约束,可以同时一起使用:

class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new() { // ... }

default 关键字

这个关键可以使用在类型参数上:

default(T);

对于值类型,返回0,引用类型,返回null,对于结构类型,会返回一个成员值全部为0的结构实例。

迭代器(iterator)

可以在不实现IEnumerable就能使用foreach语句,在编译器碰到yield return时,它会自动生成IEnumerable 接口的方法。在实现迭代器的方法或属性中,返回类型必须是IEnumerable, IEnumerator, IEnumerable<T>,或 IEnumerator<T>。迭代器使得遍历一些零碎数据的时候很方便,不用去实现Current, MoveNext 这些方法。

public System.Collections.IEnumerator GetEnumerator() { yield return -1; for (int i = 1; i < max; i++) { yield return i; } }

可空类型(Nullable Type)

可空类型System.Nullable<T>,可空类型仅针对于值类型,不能针对引用类型去创建。System.Nullable<T>简写为T ?。

int? num = null; if (num.HasValue == true) { System.Console.WriteLine("num = " + num.Value); } else { System.Console.WriteLine("num = Null"); }

如果HasValue为false,那么在使用value值的时候会抛出异常。把一个Nullable的变量x赋值给一个非Nullable的变量y可以这么写:

int y = x ?? -1;

匿名方法(Anonymous Method)

在C#2.0之前,给只能用一个已经申明好的方法去创建一个委托。有了匿名方法后,可以在创建委托的时候直接传一个代码块过去。

delegate void Del(int x); Del d = delegate(int k) { /* ... */ }; System.Threading.Thread t1 = new System.Threading.Thread (delegate() { System.Console.Write("Hello, "); } ); 委托语法的简化// C# 1.0的写法 ThreadStart ts1 = new ThreadStart(Method1); // C# 2.0可以这么写 ThreadStart ts2 = Method1;


委托的协变和逆变(covariance and contravariance)

有下面的两个类:

class Parent { } class Child: Parent { }

然后看下面的两个委托:

public delegate Parent DelgParent();

public delegate Child DelgChild();

public static Parent Method1() { return null; }

public static Child Method2() { return null; }

static void Main() { DelgParent del1= Method1; DelgChild del2= Method2; del1 = del2; }

注意上面的,DelgParent 和DelgChild 是完全不同的类型,他们之间本身没有任何的继承关系,所以理论上来说他们是不能相互赋值的。但是因为协变的关系,使得我们可以把DelgChild类型的委托赋值给DelgParent 类型的委托。协变针对委托的返回值,逆变针对参数,原理是一样的。

部分类(partial)

在申明一个类、结构或者接口的时候,用partial关键字,可以让源代码分布在不同的文件中。我觉得这个东西完全是为了照顾Asp.net代码分离而引入的功能,真没什么太大的实际用处。微软说在一些大工程中可以把类分开在不同的文件中让不同的人去实现,方便团队协作,这个我觉得纯属胡扯。

部分类仅是编译器提供的功能,在编译的时候会把partial关键字定义的类和在一起去编译,和CRL没什么关系。

静态类(static class)

静态类就一个只能有静态成员的类,用static关键字对类进行标示,静态类不能被实例化。静态类理论上相当于一个只有静态成员并且构造函数为私有的普通类,静态类相对来说的好处就是,编译器能够保证静态类不会添加任何非静态成员。

global::

这个代表了全局命名空间(最上层的命名空间),也就是任何一个程序的默认命名空间。

class TestApp { public class System { } const int Console = 7; static void Main() { //用这个访问就会出错,System和Console都被占用了 //Console.WriteLine(number); global::System.Console.WriteLine(number); } }

extern alias

用来消除不同程序集中类名重复的冲突,这样可以引用同一个程序集的不同版本,也就是说在编译的时候,提供了一个将有冲突的程序集进行区分的手段。

在编译的时候,使用命令行参数来指明alias,例如:

/r:aliasName=assembly1.dll

在Visual Studio里面,在被引用的程序集的属性里面可以指定Alias的值,默认是global。

然后在代码里面就可以使用了:

extern alias aliasName;

//这行需要在using这些语句的前面

using System; using System.Collections.Generic;

using System.Text; using aliasName.XXX;

属性Accessor访问控制

public virtual int TestProperty { protected set { } get { return 0; } }

友元程序集(Friend Assembly)

可以让其它程序集访问自己的internal成员(private的还是不行),使用Attributes来实现,例如:

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

注意这个作用范围是整个程序集。

fixed关键字

可以使用fixed关键字来创建固定长度的数组,但是数组只能是bool, byte, char, short, int, long, sbyte, ushort, uint, ulong, float, double中的一种。

这主要是为了更好的处理一些非托管的代码。比如下面的这个结构体:

public struct MyArray { public fixed char pathName[128]; }

如果不用fixed的话,无法预先占住128个char的空间,使用fixed后可以很好的和非托管代码进行交互。

volatile关键字

用来表示相关的字可能被多个线程同时访问,编译器不会对相应的值做针对单线程下的优化,保证相关的值在任何时候访问都是最新的。

#pragma warning

用来取消或者添加编译时的警告信息。每个警告信息都会有个编号,如果warning CS01016之类的,使用的时候取CS后面的那个数字,例如:

#pragma warning disable 414, 3021

这样CS414和CS3021的警告信息就都不会显示了。

C# 2.0新加特性的更多相关文章

  1. C# 7.0新加特性

    以下将是 C# 7.0 中所有计划的语言特性的描述.随着 Visual Studio “15” Preview 4 版本的发布,这些特性中的大部分将活跃起来.现在是时候来展示这些特性,你也告诉借此告诉 ...

  2. C# 5.0新加特性

    1. 异步编程 在.Net 4.5中,通过async和await两个关键字,引入了一种新的基于任务的异步编程模型(TAP).在这种方式下,可以通过类似同步方式编写异步代码,极大简化了异步编程模型.如下 ...

  3. C# 6.0新加特性

    1.自动属性的增强 1.1.自动属性初始化 (Initializers for auto-properties) C#4.0下的果断实现不了的. C#6.0中自动属性的初始化方式 只要接触过C#的肯定 ...

  4. C# 4.0新加特性

    协变和逆变 这个在C#2.0中就已经支持委托的协变和逆变了,C#4.0开始支持针对泛型接口的协变和逆变: IList<string> strings = new List<strin ...

  5. C# 3.0新加特性

    类型推断 申明变量的时候,可以不用直指定类型: var i = 5; var s = "Hello"; //两种写法是一样的 int i = 5; string s = " ...

  6. LINQ体验(2)——C# 3.0新语言特性和改进(上篇)

    整体来说.Visual Studio 2008和.NET 3.5是建立在.NET2.0核心的基础之上,.NET2.0核心本身将不再变化(假设不了解.NET2.0的朋友,请參看MSDN或者一些经典的书籍 ...

  7. C# 3.0新语言特性和改进(一)

    引言 关于C#3.0的特性,园子里已经有了一大把,可能大家都很熟悉了,虽然本人开发中使用过,但自己还是需要记录一下,总结一下.同时也是后面写Linq知识的基础.希望有兴趣的朋友,可以看看. C# 3. ...

  8. Netty 4.0 新的特性及需要注意的地方

    Netty 4.0 新的特性及需要注意的地方 这篇文章和你一起过下Netty的主发行版本的一些显著的改变和新特性,让你在把你的应用程序转换到新版本的时候有个概念. 项目结构改变 Netty的包名从or ...

  9. dbt 0.13.0 新添加特性sources 试用

    dbt 0.13 添加了一个新的功能sources 我呢可以用来做以下事情 从基础模型的源表中进行数据选择 测试对于源数据的假设 计算源数据的freshness source 操作 定义source ...

随机推荐

  1. apicloud 注意事项

    页面布局时头部和内容一定要分开,状态栏寖入式要用.可以用api.sendEvent广播出去,api.addlisterten监听. api.openWin打开页面会有黑色闪屏,加bgColor:'#f ...

  2. codeforces 467C George and Job(简单dp,看了题解抄一遍)

    题目 参考了网页:http://www.xue163.com/exploit/180/1802901.html //看了题解,抄了一遍,眼熟一下,增加一点熟练度 //dp[i][j]表示是前i个数选出 ...

  3. Wireshark 如何捕获网络流量数据包

    转自:http://www.4hou.com/web/7465.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutia ...

  4. Python语言数据结构和语言结构(2)

    目录 1. Python预备基础 2. Python数据类型 3. Python条件语句 4. while循环和for循环 1. Python预备基础 1.1 变量的命名   变量命名规则主要有以下几 ...

  5. MySQL特异功能之:Impossible WHERE noticed after reading const tables

    用EXPLAIN看MySQL的执行计划时经常会看到Impossible WHERE noticed after reading const tables这句话,意思是说MySQL通过读取"c ...

  6. @Resource与@Autowired区别

    每次理解清楚,过段时间就忘了,还是记一下,方便之后再回看. @ Autowired 是spring提供,包含3种自动装配Bean形式 1.@Autowired默认按类型byType匹配,自动装配Bea ...

  7. 第三篇:SpringBoot - 数据库结构版本管理与迁移

    SpringBoot支持了两种数据库结构版本管理与迁移,一个是flyway,一个是liquibase.其本身也支持sql script,在初始化数据源之后执行指定的脚本,本章是基于 Liquibase ...

  8. session_start() [function.session-start]:

    我在学习PHP的,当我尝试做在session_start() - 获取有关错误信息不能发送会话cookie. 我看到在这个问题上前面的问题,可是,仍然不能确定我的错误. 假设是错误家伙? <? ...

  9. Centos6.2中配置tomcat

    这里我使用的是tomcat6, 我使用的是server版本号的Centos, 前提是安装而且配置好了JDK. 首先通过samba把我的tomcat压缩包, 复制到了共享的文件夹.然后移动到./usr文 ...

  10. 金融扫盲-资本市场从天使轮、ABCD轮、风投、到上市圈钱、借壳上市。

    转载请标明出处:http://blog.csdn.net/hu948162999/article/details/47777859 对于金融知识零基础的人进行扫盲,故事浅显易懂.趣味性强. 来之知乎. ...