日期:2012-07-28  浏览次数:20420 次

当考虑到C++是怎么做的时候,Java是干了件好事,它简化了参数如何传递的问题。在C++中,方法【译注:C++中没有方法一说,应该称为“函数”或“成员函数”】的参数和方法调用通过传值、引用、指针【译注:例如int、int*、int&】,使得代码变得不必要的复杂。C#显式传递引用,不管是方法声明时还是调用时。它大大地减少了混乱【译注:这句话应该这么理解:由于C++的语法问题,有时你并不知道你是在使用一个对象还是一个对象引用,本节后有示例】,并达到了和Java同样的目标,但是C#的方式更有表达力。显然这是C#的主旨—它不把程序员圈在一个圈里,使他们必须绕一个大弯子才能做成某件事。还记得Java吗?Java指南里,建议如何解决传引用的问题,你应该传递一个1个元素的数组去保存你的值,或另做一个类以保存这个值。
【译注:
#include "stdafx.h"
class ParentCls
{
public:
     virtual void f(){printf("ParentCls\t");}
};
class ChildCls : public ParentCls
{
public:
     virtual void f(){printf("ChildCls\t");}
};
void Test1(ParentCls pc) {pc.f();}
void Test2(ParentCls& pc) {pc.f();}
int main(int argc, char* argv[])
{
    ChildCls cc;
     Test1(cc);//输出ParentCls
     Test2(cc);//输出ChildCls
     //只看调用处,是不知道你使用的引用还是对象的,但运行结果迥异!
     return 0;
}

15.特性
     C#和Java的编译代码里都包括类似于字段访问级别的信息。C#扩展了这个能力,对类中的任何元素,比如类、方法、字段甚至是独立参数,你都可以编译自定义的信息,并可以于运行时获取这些信息。这儿有一个非常简单的使用特性的类的例子:
[AuthorAttribute ("Ben Albahari")]
class A
{
    [Localizable(true)]
    public String Text //【译注:应为public string Text或public System.String Text,如果前面没有using System的话】
    {
        get {return text;}
        //...
    }
}
Java使用一对/** */和@标签注释以包含类和方法的附加信息,但这些信息(除了@deprecated【译注:Java1.1版本及以后】)并未build到字节码中。C#使用预定义的特性Obsolete特性,编译器可以警告你,排除废代码(就象@deprecated),并用Conditional特性使得可以条件编译。微软新的XML库使用特性来表达字段如何序列化到XML中,这就意味着你可以很容易地把一个类序列化到XML中,并可以再次重建它。另外一个对特性的恰当的应用是创建真正有威力的类浏览工具。C#语言规范详尽第解释了怎样创建和使用特性。
16.switch语句
     C#中的switch语句可以使用整型、字符、枚举或(不象C++或Java)字符串。在Java和C++中,如果你在任何一个case语句里忽略了一个break语句,你就有其它case语句被执行的危险。我想不通为什么这个很少需要的并容易出错的行为在Java和C++中都成了缺省行为,我也很高兴地看到C#不会是这个样子。
【译注: 因为C#不支持从一个case标签贯穿到另一个case标签。如果需要的话,可以使用goto case或goto default实现】
17.预定义类型
     C#基本类型基本上和Java的差不多,除了前者还加入了无符号的类型。C#中有sbyte、byte、short、ushort、int、uint、long、ulong、char、float和double。唯一令人感到惊奇的地方是这儿有一个16个字节【译注:原文误写为12个字节】的浮点型数值类型decimal,它可以充分利用最新的处理器。
【译注:补充一下,尽管decimal占用128位,但它的取值范围比float(32位)、Double(64位)远远小得多,但它的精度比后二者的要高得多,可以满足精度要求极高的财务计算等】
18.字段修饰符
     C#中字段修饰符基本上Java相同。为了表示不可被修改的字段,C#使用const和readonly修饰符。const字段修饰符就象Java的final字段修饰符,该字段的实际值被编译成IL代码的一部分。只读字段在运行时计算值。对标准C#库来说,这就可以在不会破坏你的已经部署的代码的前提下升级。
19.跳转语句
     这儿没有更多的令人惊讶的地方,可能除了臭名卓著的goto语句。然而,这和我们记得的带来麻烦的20年前的basic的goto语句大不相同。一个goto语句必须指向一个标签【译注:goto语句必须必须在该标签的作用域内,或者换句话说,只允许使用goto语句将控制权传递出一个嵌套的作用域,而不能将控制权传递进一个嵌套域】或是switch语句里的一个选择支【译注:即所谓的goto case语句】。指向标签的用法和continue差不多。Java里的标签,自由度大一些【译注:Java中的break和continue语句后可跟标签】。C#中,goto语句可以指向其作用域的任意一个地方,这个作用域是指同一个方法或finally程序块【译注:如果goto语句出现在finally语句块内,则goto语句的目的地也必须在同一个finally语句块内】。C#中的continue语句和Java中的基本等价,但C#中不可以指向一个标签。
【译注:Java把goto作为保留字,但并未实现它】
20.组合体、名字空间和访问级别
     在C#中,你可以把你源代码中的组件(类、结构、委托、枚举等)组织到文件、名字空间和组合体中。
     名字空间不过是长类名的语法上的甜言蜜语而已。例如,用不着这么写Genamics.WinForms.Grid,你可以如此声明类Grid并将其包裹起来:
namespace Genamics.WinForms
{
    public class Grid
    {
        //....
    }
}
对于使用Grid的类,你可以用using关键字导入【译注:即using Genamics.WinForms】,而不必用其完整类名Genamics.WinForms.Grid。
     组合体是从项目文件编译出来的exe或dll。.NET运行时使用可配置的特性和版本法则,把它们创建到组合体,这大大简化了部署—不需要写注册表,只要把组合体拷到相关目录中去即可。组合体还可以形成一个类型边界,从而解决类名冲突问题。同一组合体的多个版本可以共存于同一进程。每一个文件都可以包含多个类、多个名字空间。一个名字空间可以横跨若干个组合体。如此以