C♯
编程范型 | 结构化、面向对象、泛型 |
---|---|
设计者 | 微软 |
实作者 | 微软 |
发行时间 | 2001年 |
当前版本 | |
操作系统 | Windows、Linux、Mac OS X |
许可证 | CLR Proprietary |
文件扩展名 | .cs |
网站 | C# Language (MSDN) |
主要实作产品 | |
.NET Framework, Mono, DotGNU | |
衍生副语言 | |
Cω, Spec#, Polyphonic C# | |
启发语言 | |
C++, Java, Eiffel, Modula-3, Object Pascal | |
影响语言 | |
D语言, F#, Java 5, Nemerle, Vala |
C#是微软推出的一种基于.NET框架的、面向对象的高级编程语言。C#由C语言和C++派生而来,继承了其强大的性能,同时又以.NET框架类库作为基础,拥有类似Visual Basic的快速开发能力。C#由安德斯·海尔斯伯格主持开发,微软在2000年发布了这种语言。
命名
C#的发音为C Sharp,“#”读作“sharp”(国际音标:/ʃɑ:p/),看起来像是“C++”中两个加号重叠在一起,而且在音乐中“C#”表示C升半音,为比C高一点的音节。微软借助这样的命名,表示C#在一些语言特性方面对C++的提升。微软希望借助这种语言来取代Java。C#已经成为Ecma国际和国际标准组织的标准规范。
设计目标
ECMA标准列出的C#设计目标:
- C#旨在设计成为一种“简单、现代、通用”,以及面向对象的程序设计语言
- 此种语言的实现,应提供对于以下软件工程要素的支持:强类型检查、数组维度检查、未初始化的变量引用检测、自动垃圾收集(Garbage Collection,指一种记忆体自动释放技术)。软件必须做到强大、持久,并具有较强的编程生产力。
- 此种语言为在分布式环境中的开发提供适用的组件开发应用。
- 为使程序员容易迁移到这种语言,源代码的可移植性十分重要,尤其是对于那些已熟悉C和C++的程序员而言。
- 对国际化的支持非常重要。
- C#适合为独立和嵌入式的系统编写程序,从使用复杂操作系统的大型系统到特定应用的小型系统均适用。
- 虽然C#程序在存储和操作能力需求方面具备经济性,但此种语言并不能在性能和程式大小方面与C语言或汇编语言相抗衡。[来源请求]
历史
原Borland公司的首席研发设计师安德斯·海尔斯伯格(Anders Hejlsberg)在微软开发了Visual J++ 1.0,很快的Visual J++由1.1版本升级到6.0版。SUN公司认为Visual J++ 违反了Java开发平台的中立性,对微软提出了诉讼。2000年6月26日微软在奥兰多举行的“职业开发人员技术大会”(PDC 2000)上,发表新的语言C#。C#语言取代了Visual J++,语言本身深受Visual Basic、Java、C和C++ 的影响。
版本
版本 | 语言规格 | 日期 | .NET框架的版本 | Visual Studio的版本 | ||
---|---|---|---|---|---|---|
ECMA | ISO/IEC | Microsoft | ||||
C# 1.0 | 2002年12月 | 2003年四月 | 2002年一月 | 2002年一月 | .NET Framework 1.0 | Visual Studio .NET 2002 |
C# 1.2 | 2003年十月 | 2003年四月 | .NET Framework 1.1 | Visual Studio .NET 2003 | ||
C# 2.0 | 2006年六月 | 2006年九月 | 2005年九月 | 2005年11月 | .NET Framework 2.0 | Visual Studio 2005 |
C# 3.0 | 2007年八月 | 2006年11月 | .NET Framework 3.5 | Visual Studio 2008 | ||
C# 4.0 | 2010年四月 | 2010年四月 | .NET Framework 4 | Visual Studio 2010 | ||
C# 5.0 | 2012年十月 | 2012年4月 | .NET Framework 4.5 | Visual Studio 2012 |
语言特性
- 指针(Pointer)只能被用于不安全模式。大多数对象访问通过安全的引用实现,以避免无效的调用,并且有许多算法用于验证溢出,指针只能用于调用值类型,以及受垃圾收集控制的托管对象。
- 对象不能被显式释放,代替为当不存在被引用时通过垃圾回收器回收。
- 只允许单一继承(single inheritance),但是一个类可以实现多个接口(interfaces)。
- C#比C++更加类型安全。默认的安全转换是隐含转换,例如由短整型转换为长整型和从派生类转换为基类。而接口布尔型同整型,及枚举型同整型不允许隐含转换,非空指针(通过引用相似对象)同用户定义类型的隐含转换字段被显式的确定,不同于C++的复制构造函数。
- 数组声明语法不同("int[] a = new int[5]"而不是"int a[5]")。
- 枚举位于其所在的命名空间中。
- C#中没有模版(Template),但是在C# 2.0中引入了泛型(Generic programming),并且支持一些C++模版不支持的特性。比如泛型参数中的类型约束。另一方面,表达式不能像C++模版中被用于类型参数。
- 属性支持,使用类似访问成员的方式调用。
- 完整的反射支持。
C# 2.0的特性
针对于.NET SDK 2.0(相对应于ECMA-334标准第三版),C# 的新特性有:
分部类别
分部类别将类别的实现分在多个文件中。该概念于C# 中首次出现,除了能将一个类别的成员分开存放,还使ASP.NET中的代码后置得以实现。代码后置实现了HTML代码和后台交互代码的分离。
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使用具化生成泛型参数,它允许优化和保存类型信息。[3]
静态类别
静态类别它不能被实例化,并且只能有静态成员。这同很多过程语言中的模块概念相类似。
迭代器
一种新形式的迭代器它提供了函数式编程中的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;
}
}
匿名方法
public void Foo(object parameter)
{
// ...
ThreadPool.QueueUserWorkItem(delegate
{
// anonymous delegates have full access to local variables of the enclosing method
if(parameter == ...)
{
// ...
}
// ...
});
}
委托的协变和逆变
属性访问器可以被单独设置访问级别
例子:
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# 3.0发布于2007年10月17日,是.NET Framework 3.5的一部分,它的新特性灵感来自于函数式编程语言,如:Haskell和ML,并广泛地引入了Language Integrated Query(LINQ)模式到通用语言运行库中e.[6]
Linq
语言集成查询(英语:Language Integrated Query,缩写:LINQ):[7] 上下文相关关键字"from
, where
, select
"可用于查询SQL、XML、集合等。这些标识符在LINQ上下文中被作为关键字,但是它们的增加不会破坏原有的名为from
、where
或select
的变量。
类型初始化器
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[8]
匿名类型
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;
set;
}
扩展方法
扩展方法指,一个静态类包含this关键字作为方法的第一参数时,这个方法将被添加到该this的类型中:
public static class IntExtensions
{
public static void PrintPlusOne(this int x)
{
Console.WriteLine(x + 1);
}
}
int foo = 0;
foo.PrintPlusOne();
分部方法
允许代码生成器生成方法声明作为扩展点,如果有人在另一个部分类实现了它才会被包含于原代码编译。[9]
- 分部方法(Partial methods)必须定义在分部类(partial classes)中
- 定义分部方法需要用partial做修饰符
- 分部方法不一定总是有执行内容的,也就是说定义的方法可以一句操作语句都没有
- 分部方法返回值必须是void
- 分部方法可以是静态(static)方法
- 分部方法可以包含参数,参数可以包含以下修饰词:this,ref,params
- 分部方法必须是私有(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, Python或Ruby。
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)。现在有一些独立的实现正在进行,包括:
- 自由软件基金会的dotGNU Portable.NET
- Mono
- Baltie - C# IDE for children and young Baltie
C# 的Hello World程式
下面是一个在命令行上输出Hello World的小程序,这种程序通常作为开始学习程序语言的第一个步骤:
using System;
public class HelloWorld {
public static void Main(string[] args) {
Console.WriteLine("Hello world!");
}
}
实现
C# 有5个著名的编译器(compilers):
- 最标准的C# 的实现当属微软自己推出、并被包含在.NET Framework内的C# 编译器。
- 微软的Rotor项目(Rotor Project,目前称为Shared Source Common Language Infrastructure),提供了通用语言运行庫(Common Language Runtime)的实现与c# 编译器。
- 由Novell赞助的Mono 项目提供了C# 编译器,同时也接近百分之百地实现了.NET Framework类库。
- Dot GNU 项目也提供了另一个自由版本的C# 编译器,也提供了.NET Framework类库的实现。
- Borland提供了项目级的C# 集成开发环境,内部所使用的编译器仍是微软.NET Framework所提供的C# 编译器(这也意味著你仍须安装微软的.NET Framework)。产品:C# Builder(商业版本),Turbo C# Explorer(免费版本)。
参考文献
- ^ https://devblogs.microsoft.com/dotnet/announcing-dotnet-9/.
- ^ https://learn.microsoft.com/en-gb/dotnet/csharp/whats-new/csharp-13.
- ^ An Introduction to C# Generics
- ^ Anonymous Methods (C#)
- ^ Covariance and Contravariance in Delegates (C#)
- ^ Tim Anderson. C# pulling ahead of Java - Lead architect paints rosy C# picture. Reg Developer. The Register. November 14 2006 [2007-01-20].
- ^ LINQ. Microsoft MSDN. 2007 [2007-08-13] (English).
- ^ The Mellow Musings of Dr. T : What is a collection?
- ^ Partial Methods. [2007-10-06].