一C#C++和Java
C#的语言规范由Microsoft的Anders Hejlsberg与Scott Wiltamuth编写在当前Microsoft天花乱坠的宣传中对C#和C++Java作一番比较总是很有趣的考虑到当前IT媒体的舆论倾向如果你早就知道C#更接近Java而不是C++事情也不值得大惊小怪对于刚刚加入这场讨论的读者下面的表让你自己作出判断显然结论应该是Java和C#虽然不是孪生子但C#最主要的特色却更接近Java而不是C++
了解表总结的重要语言功能之后请继续往下阅读了解C#和Java的一些重要区别
二语言规范的比较
简单数据类型
简单数据类型(Primitive)在C#中称为值类型C#预定义的简单数据类型比Java多例如C#有unit即无符号整数表列出了所有C#的预定义数据类型
常量
忘掉Java中的static final修饰符在C#中常量可以用const关键词声明
public const int x = ;
此外C#的设计者还增加了readonly关键词如果编译器编译时未能确定常量值你可以使用readonly关键词readonly域只能通过初始化器或类的构造函数设置
公用类的入口点
在Java中公用类的入口点是一个名为main的公用静态方法main方法的参数是String对象数组它没有返回值在C#中main方法变成了公用静态方法Main(大写的M)Main方法的参数也是一个String对象数组而且也没有返回值如下面的原型声明所示
public static void Main(String[] args)
但是C#的Main方法不局限于此如果不向Main方法传递任何参数你可以使用上述Main方法的一个重载版本即不带参数列表的版本也就是说下面的Main方法也是一个合法的入口点
public static void Main()
另外如果你认为有必要的话Main方法还可以返回一个int例如下面代码中的Main方法返回
using System;
public class Hello {
public static int Main() {
ConsoleWriteLine(Done);
return ;
}
}
与此相对在Java中重载main方法是不合法的
switch语句
在Java中switch语句只能处理整数但C#中的switch语句不同它还能够处理字符变量请考虑下面用switch语句处理字符串变量的C#代码
using System;
public class Hello {
public static void Main(String[] args) {
switch (args[]) {
case 老板:
ConsoleWriteLine(早上好!我们随时准备为您效劳!);
break;
case 雇员:
ConsoleWriteLine(早上好!你可以开始工作了!);
break;
default:
ConsoleWriteLine(早上好!祝你好运!);
break;
}
}
}
与Java中的switch不同C#的switch语句要求每一个case块或者在块的末尾提供一个break语句或者用goto转到switch内的其他case标签
foreach语句
foreach语句枚举集合中的各个元素为集合中的每一个元素执行一次代码块请参见下面的例子
using System;
public class Hello {
public static void Main(String[] args) {
foreach (String arg in args)
ConsoleWriteLine(arg);
}
}
如果在运行这个执行文件的时候指定了参数比如Hello Peter Kevin Richard则程序的输出将是下面几行文字
Peter
Kevin
Richard
C#没有>>>移位操作符
C#支持uint和ulong之类的无符号变量类型因此在C#中右移操作符(即>>)对于无符号变量类型和带符号变量类型(比如int和long)的处理方式不同右移uint和ulong丢弃低位并把空出的高位设置为零但对于int和long类型的变量>>操作符丢弃低位同时只有当变量值是正数时>>才把空出的高位设置成零如果>>操作的是一个负数空出的高位被设置成为
Java中不存在无符号的变量类型因此我们用>>>操作符在右移时引入负号位否则使用>>操作符
goto关键词
Java不用goto关键词在C#中goto允许你转到指定的标签不过C#以特别谨慎的态度对待goto比如它不允许goto转入到语句块的内部在Java中你可以用带标签的语句加上break或continue取代C#中的goto
声明数组
在Java中数组的声明方法非常灵活实际上有许多种声明方法都属于合法的方法例如下面的几行代码是等价的
int[] x = { };
int x[] = { };
但在C#中只有第一行代码合法[]不能放到变量名字之后
包
在C#中包(Package)被称为名称空间把名称空间引入C#程序的关键词是using例如using System;这个语句引入了System名称空间
然而与Java不同的是C#允许为名称空间或者名称空间中的类指定别名
using TheConsole = SystemConsole;
public class Hello {
public static void Main() {
TheConsoleWriteLine(使用别名);
}
}
虽然从概念上看Java的包类似于NET的名称空间然而两者的实现方式不同在Java中包的名字同时也是实际存在的实体它决定了放置java文件的目录结构在C#中物理的包和逻辑的名称之间是完全分离的也就是说名称空间的名字不会对物理的打包方式产生任何影响在C#中每一个源代码文件可以从属于多个名称空间而且它可以容纳多个公共类
NET中包的实体称为程序集(Assembly)每一个程序集包含一个manifest结构manifest列举程序集所包含的文件控制哪些类型和资源被显露到程序集之外并把对这些类型和资源的引用映射到包含这些类型与资源的文件程序集是自包含的一个程序集可以放置到单一的文件之内也可以分割成多个文件NET的这种封装机制解决了DLL文件所面临的问题即臭名昭着的DLL Hell问题
默认包
在Java中javalang包是默认的包它无需显式导入就已经自动包含例如要把一些文本输出到控制台你可以使用下面的代码
Systemoutprintln(Hello world from Java);
C#中不存在默认的包如果要向控制台输出文本你使用System名称空间Console对象的WriteLine方法但是你必须显式导入所有的类代码如下
using System;
public class Hello {
public static void Main() {
ConsoleWriteLine(Hello world from C#);
}
}
面向对象
Java和C#都是完全面向对象的语言在面向对象编程的三大原则方面这两种语言接近得不能再接近
继承这两种语言都支持类的单一继承但类可以实现多个接口所有类都从一个公共的基类继承
封装与可见性无论是在Java还是C#中你都可以决定类成员是否可见除了C#的internal访问修饰符之外两者的可见性机制非常相似
多态性Java和C#都支持某些形式的多态性机制且两者实现方法非常类似
可访问性
类的每个成员都有特定类型的可访问性C#中的访问修饰符与Java中的基本对应但多出了一个internal简而言之C#有种类型的可访问性如下所示
public成员可以从任何代码访问
protected成员只能从派生类访问
internal成员只能从同一程序集的内部访问
protected internal成员只能从同一程序集内的派生类访问
private成员只能在当前类的内部访问
派生类
在Java中我们用关键词extends实现继承C#采用了C++的类派生语法例如下面的代码显示了如何派生父类Control从而创建出新类Button
public class Button: Control { }
最终类
由于C#中不存在final关键词如果想要某个类不再被派生你可以使用sealed关键词如下例所示
sealed class FinalClass { }
接口
接口这个概念在C#和Java中非常相似接口的关键词是interface一个接口可以扩展一个或者多个其他接口按照惯例接口的名字以大写字母I开头下面的代码是C#接口的一个例子它与Java中的接口完全一样
interface IShape { void Draw(); }
扩展接口的语法与扩展类的语法一样