代码改变世界

C#特性

2012-03-12 17:42  AceYue  阅读(622)  评论(0编辑  收藏  举报

C# 2.0 的特性

针对于.NET SDK 2.0(相对应于ECMA-334 标准第三版),C# 的新特性有:

[编辑] 分部类

分部类将类型的实现分在多个文件中。

file1.cs:

public partial class MyClass1
{
    public void MyMethod1()
    {
        // implementation
    }
}

file2.cs:

public partial class MyClass1
{
    public void MyMethod2()
    {
        // implementation
    }
}

分部类这个特性允许将一个类的编写工作分配给多个人,一人写一个文件,便于版本控制。它又可以隔离自动生成的代码和人工书写的代码,例如设计窗体应用程序时。

[编辑] 泛型

泛型,或参数化类型,是被C#支持的.NET 2.0特性。不同于C++模版,.NET 参数化类型是在运行时被实例化,而不是编译时,因此它可以跨语言,而C++模版却不行。它支持的一些特性并不被C++模版直接支持,比如约束泛型参数实现一个接口。另一方面,C# 不支持无类型的泛型参数。不像Java中的泛型,在CLI虚拟机中,.NET generics 使用 具化 生成泛型参数,它允许优化和保存类型信息。[1]

[编辑] 静态类

静态类它不能被实例化,并且只能有静态成员。这同很多过程语言中的模块概念相类似。

[编辑] 迭代器

一种新形式的迭代器 它提供了函数式编程中的generator,使用yield return

类似于Python中使用的yield

// Method that takes an iterable input (possibly an array)
// and returns all even numbers.
public static IEnumerable<int> GetEven(IEnumerable<int> numbers)
{
    foreach (int i in numbers)
    {
        if (i % 2 == 0) yield return i;
    }
}

[编辑] 匿名方法

匿名方法类似于函数式编程中的闭包[2]

public void Foo(object parameter)
{
    // ...
 
    ThreadPool.QueueUserWorkItem(delegate
    {
        // anonymous delegates have full access to local variables of the enclosing method
        if (parameter == ...)
        { 
            // ... 
        }
 
        // ...
    });
}

[编辑] 委托的协变和逆变

委托签名的协变和逆变,[3]

[编辑] 属性访问器可以被单独设置访问级别

例子:

string status = string.Empty;
 
public string Status
{
    get { return status; }             // anyone can get value of this property,
    protected set { status = value; }  // but only derived classes can change it
}

[编辑] 可空类型

可空类型 (跟个问号, 如 int? i = null;) 允许设置 null 给任何类类型。

int? i = null;
object o = i;
if (o == null)
    Console.WriteLine("Correct behaviour - runtime version from September 2005 or later");
else
    Console.WriteLine("Incorrect behaviour - pre-release runtime (from before September 2005)");

[编辑] ??操作符

(??) 用于如果类不为空值时返回它自身,如果为空值则返回之后的操作

object nullObj = null; 
object obj = new Object(); 
return nullObj ?? obj; // returns obj

主要用作将一个可空类型赋值给不可空类型的简便语法

int? i = null;
int j = i ?? 0; // Unless i is null, initialize j to i. Else (if i is null), initialize j to 0.

[编辑] C# 3.0 的特性

C# 作为当前版,发布于2007年10月17日,是.NET Framework 3.5 的一部分, 它的新特性灵感来自于函数式编程语言,如:HaskellML,并广泛地引入了Language Integrated Query (LINQ) 模式到通用语言运行库中e.[4]

[编辑] Linq

语言集成查询英语Language Integrated Query,缩写:LINQ):[5] 上下文相关关键字"from, where, select" 可用于查询SQL、XML、集合等。这些标识符在LINQ上下文中被作为关键字,但是它们的增加不会破坏原有的名为fromwhereselect的变量。

[编辑] 类型初始化器

Customer c = new Customer();
c.Name = "James";

可写作:

Customer c = new Customer { Name="James" };

[编辑] 集合初始化器

MyList list = new MyList();
list.Add(1);
list.Add(2);

可写作

MyList list = new MyList { 1, 2 };

假设 MyList 实现了 System.Collections.IEnumerable 且有一个Add 方法method[6]

[编辑] 匿名类型

var x = new { Name="James" };

[编辑] 局部变量类型推断

局部变量 类型推断:

var x = new Dictionary<string, List<float>>();

等同于

Dictionary<string, List<float>> x = new Dictionary<string, List<float>>();

它只是一个语法糖, 这个特性被匿名类型声明时所需要

[编辑] Lambda表达式

Lambda表达式指:

listOfFoo.Where(
    delegate(Foo x)
    {
        return x.Size > 10; 
    }
)
可写作
listOfFoo.Where(x => x.Size > 10);

编译器翻译Lambda表达式为强类型委托或强类型表达式树.

[编辑] 自动化属性

编译器将自动生成私有变量和适当的getter(get访问器)和setter(set访问器),如:

public string Name
{
    get; 
    private set; 
}

[编辑] 扩展方法

扩展方法指,一个静态类包含this关键字作为方法的第一参数时,这个方法将被添加到该this的类型中:

public static class IntExtensions
{
    public static void PrintPlusOne(this int x) 
    {
        Console.WriteLine(x + 1);
    }
}
 
int foo = 0;
foo.PrintPlusOne();

[编辑] 分部方法

允许代码生成器生成方法声明作为扩展点,如果有人在另一个部分类实现了它才会被包含于原代码编译。[7]

  1. 分部方法 (Partial methods) 必须定义在分部类 (partial classes) 中
  2. 定义分部方法 需要用 partial 做修饰符
  3. 分部方法不一定总是有执行内容的,也就是说定义的方法 可以一句操作语句都没有
  4. 分部方法返回值必须是void
  5. 分部方法可以是静态 (static) 方法
  6. 分部方法可以包含参数,参数可以包含以下修饰词:this,ref,params
  7. 分部方法必须是私有 (private) 方法

例子:

partial class C
{
    static partial void M(int i); // defining declaration
}
partial class C
{
    static partial void M(int i)
    {
        dosomething();
    }
}

[编辑] C# 4.0的特性

[编辑] 动态查阅

C# 4.0 新增 dynamic关键字,提供动态编程(dynamic programming),把既有的静态物件标记为动态物件,类似javascript, PythonRuby

dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);

[编辑] 具名参数与可选参数

public StreamReader OpenFile(
    string path,
    int bufferSize = 1024)
{
...
}

呼叫 OpenFile 时, 顺序可以完全颠倒:

OpenFile(bufferSize: 4096, path: "foo.txt");

[编辑] 与 COM 物件互动

在 C#中打开一个Word文件:

static void Main(string[] args) {
    Word.Application wordApplication = new   
       Word.Application() {Visible = true};     
    wordApplication.Documents.Open(@"C:\plant.docx",   
       ReadOnly: true);  
}

在C#中指定Excel的某一格文字:

excelObj.Cells[5, 5].Value = "This is sample text";

[编辑] 泛型的协变和逆变

C# 4.0 支持协变和逆变,例如在泛型接口可以加上in、out关键字。

  public interface IComparer<in T>  
  {  
    public int Compare(T left, T right);  
  }
 
  public interface IEnumerable<out T> : IEnumerable
  {
    IEnumerator<T> GetEnumerator();
  }

[编辑] 程序的执行

C#并不被编译成为能够直接在计算机上执行的二进制本地代码。与Java类似,它被编译成为中间代码(Microsoft Intermediate Language),然后通过.NET Framework虚拟机——被称之为通用语言运行库Common Language Runtime)——执行。

所有的.Net编程语言都被编译成这种被称为MSIL(Microsoft Intermediate Language )的中间代码。因此虽然最终的程序在表面上仍然与传统意义上的可执行文件都具有“.exe”的后缀名。但是实际上,如果计算机上没有安装.Net Framework,那么这些程序将不能够被执行。

在程序执行时,.Net Framework将中间代码翻译成为二进制机器码,从而使它得到正确的运行。最终的二进制代码被存储在一个缓冲区(Buffer)中。所以一旦程序使用了相同的代码,那么将会调用缓冲区中的版本。这样如果一个.Net程序第二次被运行,那么这种翻译不需要进行第二次,速度明显加快。

[编辑] 标准化

微软公司已经向ECMA申请将C#作为一种标准。在2001年12月,ECMA发布了ECMA-334 C#语言规范。C#在2003年成为一个ISO标准(ISO/IEC 23270)。现在有一些独立的实现正在进行,包括:

[编辑] C#的Hello World程式

下面是一个在命令行上输出Hello World的小程序,这种程序通常作为开始学习程序语言的第一个步骤:

using System;
class HelloWorld
{
  public static void Main(string[] args)
  {
    Console.WriteLine("Hello, world!");
  }
}

[编辑] 实现

C# 有5个著名的编译器(compilers):