泛型(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. 单调队列 && 单调栈

    单调队列 && 单调栈 单调队列 维护某个滑动区间的min or max,可用于dp的优化 以维护min为例,采用STL双端队列实现 每次加入元素x前 先检查队首元素==滑动后要删除的 ...

  2. 一个简单的执行程序的GNU automake自动生成Makefile的方法及案例

    一个简单的执行程序的GNU automake自动生成Makefile的方法及案例 在GNU的世界里,存在Automake这样的工具进行自动生成Makefile文件,automake是由Perl语言编写 ...

  3. 在oracle中将某个字段的数据作为列名的查询

    原表结构 查询语句: select sno,sname,sum(语文) 语文,sum(数学) 数学,sum(英语) 英语 from (select sno,sname,decode(subjiect, ...

  4. [luogu3230 HNOI2013] 比赛 (搜索+Hash)

    传送门 Solution 搜索加Hash记录状态,记忆化搜索,需要注意顺序无关答案 Code //By Menteur_Hxy #include <map> #include <cm ...

  5. 教你如何检查一个函数是否为JavaScript运行时环境内建函数

    在开发过程中,对于某些API在现有的JavaScript运行时环境不支持的时候,我们大都会采用加入polyfill来解决这个问题.但有些时候我们可能需要知道现在某个API到底是否为运行时环境所原生支持 ...

  6. c#打包时 Could not find file "I:\VS2012\myWork\SmartCam\SmartCam\bin\Debug\Emgu.CV.DebuggerVisualizers.VS2012.dll" ISEXP : error : -6103: Could not find file "I:\VS2012\myWork\SmartCam\SmartCam\bin

    1.错误:C#打包时发生如下错误: 错误 1 -6103: Could not find file "I:\VS2012\myWork\SmartCam\SmartCam\bin\Debug ...

  7. mybatis源码阅读-Transaction和TransactionFactory(四)

    Transaction 类图 接口定义 public interface Transaction { Connection getConnection() throws SQLException; v ...

  8. SSL延迟

    原文链接 据说,Netscape公司当年设计SSL协议的时候,有人提过,将互联网所有链接都变成HTTPs开头的加密链接. 这个建议没有得到采纳,原因之一是HTTPs链接比不加密的HTTP链接慢很多.( ...

  9. Maven错误:XXX时出错; invalid LOC header (bad signature)的解决方法

    错误原因是该包没下载成功,比如网络问题等因素. 解决方法:进入本地仓库删除该包,然后再执行打包或部署等操作即可.

  10. HDU 4521

    就是那个O(nlogn)的LIS算法. #include <iostream> #include <cstdio> using namespace std; int dt[10 ...