A Comparative Overview of C#中文版(一)

中文

A Comparative Overview of C#中文版(上篇)
作者:Ben Albahari
公司:Genamics
日期:2000年7月31日初版,2000年8月10日修订。
感谢以下人士支持和反馈(按字母先后顺序):Don Box、 C.R. Manning、 Joe Nalewabau、 John Osborn、 Thomas Rhode & Daryl Richter。
译者:荣耀
【译序:C#入门经典!希望文中针对新手的译注不会影响阅读的流畅性。限于译者时间和能力,文中倘有讹误,当以英文原版为准】

本文将以C#提供的新的编程方式以及它是如何改进两个近邻—Java和C++为中心。C#在很多方面和Java用了类似的方式改进C++。因此,我不打算重复诸如单根对象层次的优点之类的东西。正文将以C#和Java的相似之处概述开始,然后着重探究C#新特性。
背景
     2000年6月,微软同时宣布了.NET平台和一个名为C#的新的编程语言。C#是一个很好地融合了简单、表达力、性能的强类型的面向对象的语言。.NET平台以公共语言运行时(类似于Java虚拟机)和一个可被多种语言(它们可以通过编译成中间语言从而可以协同工作)共用的库为中心。C#和.NET有那么一点共生关系—C#的一些特性和.NET协作得很好,反之亦然(尽管.NET的目标是和多种语言很好地协作)。本文主要关注于C#,但视需要偶尔也会提及.NET。C#的设计借鉴了多种语言,但最主要的还是Java和C++。它是由Anders Hejlsberg(大名鼎鼎的Delphi【译注:说成Object Pascal更合适些】语言设计师)和Scott Wiltamuth共同设计的。
目录
1.   C#和Java
2.   属性
3.   索引器
4.   委托
5.   事件
6.   枚举
7.   集合和foreach语句
8.   结构
9.   类型一致
10.操作符重载
11.多态
12.接口
13.版本处理
14.参数修饰符
15.特性【译注:即attribute,我在《C#首席设计师Anders Hejlsberg专访》译文中(参见CSDN的http://www.csdn.net/develop/article/11/11580.shtm)曾说过,到目前为止,该词译法仍较混乱,甚至和property不分,都被译为“属性”(Visual Studio.NET 7.0 Beta 2 的联机文档就是如此)。但本文中,仍将其译为“特性”,以示区分】
16.选择语句
17.预定义类型
18.字段修饰符
19.跳转语句
20.组合体、名字空间和访问级别【译注:Assembly一词译法比较混乱,有的译为“配件”,有的译为“组件”,有的译为“组合体”,而Visual Studio.NET 7.0 Beta2联机文档上则译为“程序集”,从技术上讲,这个译法说的倒很事实,但总感觉和这个词的外观远了点,在译法尚未统一之前,本文暂译为“组合体”】
21.指针运算
22.多维数组【译注:这一节里还谈到了交错数组】
23.构造器和析构器
24.受控执行环境
25.库
26.互用性
27.结论
1.C#和Java
下面是C#和Java共有的特性列表,目的都是为了改进C++。这些特性虽非本文重点,但了解它们之间的相似之处还是很重要的。
l          编译为机器独立、语言独立的代码,运行在受控执行环境里;
l          采用垃圾收集机制,同时摒弃了指针(C#中,指针被限制在标为unsafe的代码内使用);
l          强有力的反射能力;
l          没有头文件,所有的代码都在包或组合体里,不存在类声明的循环依赖问题;
l          所有的类都派生自object,且必须用new关键字分配在堆上;【译注:Java中为Object;C#中为object,相当于.NET的System.Object】
l          当进入标为锁定/同步代码时,通过在对象上加锁来支持多线程;【译注:例如Java中可对方法施以synchronized关键字,在C#中可使用Monitor类、Mutex类、lock语句等等】
l          接口支持—多继承接口,单继承实现;
l          内部类;
l          类继承时无需指定访问级别;【译注:在C++中,你可以这么做:class cls2: private cls1{};等等】
l          没有全局函数或常量,一切都必须属于类;
l          数组和字符串都保存长度记数并具边界检查能力;
l          永远使用“.”操作符,不再有“->”、“::”操作符;
l          null和boolean/bool是关键字;【译注:Java中为boolean、C#中为bool,相当于System.Boolean】
l          所有的值在使用前必须被初始化;
l          if语句不能使用整型数为判别条件;
l          try语句块后可以跟finally从句。【译注:标准C++不可以,但Visual C++对SEH做了扩展,可以用__try和__finally】
2.属性
     对于Delphi和Visual Basic的用户来说,属性是个熟悉的概念。使用属性的目的是将获取器/设置器[译注:原文为getter/setter]的概念正式化,这是一个被广泛使用的模式,尤其是在RAD(快速应用开发)工具里。
     以下是你可能在Java或C++里写的典型代码:
foo.setSize (getSize () + 1);
label.getFont().setBold (true);
     同样代码在C#里可能会变成:
foo.size++;
label.font.bold = true;
C#代码对于使用foo和label的用户来说更直观、更可读。在实现属性方面,差不多同样简单:
Java/C++:
public int getSize()
{
    return size;
}
public void setSize (int value)
{
    size = value;
}
C#:
public int Size
{
    get {return size;}
    set {size = value;}
}
特别是对于可读写的属性,C#提供了一个处理此概念的更清爽的方式。在C#中,get和set方法是内在的,而在Java和C++里则需人为维护。C#的处理方式有诸多优点。它鼓励程序员按照属性的方式去思考—把这个属性标为可读写的和只读的哪个更自然?或者根本不应该为属性?如果你想改变你的属性的名称,你只要检查一处就可以了(我曾看到过中间隔了几百行代码的获取器和设置器【译注:此处是指C++(Java)里对同一个数据成员/字段(一般来说是)的获取器和设置器】)。注释也只要一处就可以了,这也避免了彼此同步的问题。IDE【译注:集成开发环境】是可以帮助做这个事的(事实上,我建议他们这么做【译注:此处的“他们”应该是指微软有关人员】),但应该牢记编程上的一个基本原理—尽力做好模拟我们问题空间的抽象。一个支持属性的语言将有助于获得更好的抽象。
【作者注:关于属性的这个优点的一个反对意见认为:当采用这种语法时,你搞不清是在操纵一个字段还是属性。然而,在Java(当然也包括C#)中,几乎所有真正复杂一点的类都不会有public的字段。字段一般都只具有尽可能小的访问级别(private/protected,或语言所定义的缺省的),并且只通过获取器和设置器方法暴露,这也意味着你可以获得优美的语法。让IDE解析代码也是完全可行的,可用不同的颜色高亮显示属性,或提供代码完成信息以表明它是否是一个属性。我们还应该看到,如果一个类设计良好,这个类的用户将只关心该类的接口(或规范)【译注:此处是指该类向其客户公开(不单单是public,对其派生类来说,也可能是protected)的方法、属性(C++/Java无显式属性概念)等,这里的客户包括其派生类等等】,而不是其内部实现。另外一个可能的争论是属性不够有效率。事实上,好的编译器可以内联仅返回某个字段的获取器,这和直接访问字段一样快。说到底,即使使用字段要比获取器/设置器来的有效,使用属性还有如下好处—日后可以改变属性的字段【译注:是指可以改变获取器/设置器的实现代码部分,比如改变获取器/设置器里所操作的字段,也可以在获取器/设置器里做一些校验或修饰工作等】,而不会影响依赖于该属性的代码】
3.索引器
     C#通过提供索引器,可以象处理数组一样处理对象。特别是属性,每一个元素都以一个get或set方法暴露。
public class Skyscraper
{
    Story[] stories;
    public Story this [int index]
    {
        get
        {
            return stories [index];
        }
        set
        {
            if (value != null)
            {
                stories [index] = value;
            }
        }
    }
    //...
}
Skyscraper empireState = new Skyscraper (/*...*/);
empireState [102] = new Story ("The Top One", /*...*/);
【译注:索引器最大的好处是使代码看上去更自然,更符合实际的思考模式】
4.委托
     委托可以被认为是类型安全的、面向对象的函数指针,它可以拥有多个方法。委托处理的问题在C++中可以用函数指针处理,而在Java中则可以用接口处理。它通过提供类型安全和支持多方法改进了函数指针方式;它通过可以进行方法调用而不需要内部类适配器或额外的代码去处理多方法调用问题而改进了接口方式。委托最重要用途是事件处理,下一节将通过一个例子加以介绍。
5.事件
     C#提供了对事件的直接支持。尽管事件处理一直是编程的基本部分,但令人惊讶的是,大多数语言在正式化这个概念上所做的努力都微乎其微。如果看看现今主流框架是如何处理事件的,我们可以举出如下例子:Delphi的函数指针(称为闭包)和Java的内部类适配器,当然还有Windows API消息系统。C#使用delegate和event关键字提供了一个清爽的事件处理方案。我认为描述这个机制的最好的办法是举个例子来说明声明、触发和处理事件的过程:
// 委托声明定义了可被调用的方法签名【译注:这里的签名可以理解为“原型”】
public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel);
// 产生事件的类
public class Game
{
    //注意使用关键字
    public event ScoreChangeEventHandler ScoreChange;
    int score;
    // 属性Score
    public int Score
    {
        get
        {
            return score;
     }
        set
        {
            if (score != value)
            {
                bool cancel = false;
                ScoreChange (value, ref cancel);
                if (! cancel)
                    score = value;
            }
        }
    }
}
// 处理事件的类
public class Referee
{
    public Referee (Game game)
    {
        // 监视game中的score的分数改变
        game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange);
    }
    // 注意这个方法签名和ScoreChangeEventHandler的方法签名要匹配
    private void game_ScoreChange (int newScore, ref bool cancel)
    {
        if (newScore < 100)
            System.Console.WriteLine ("Good Score");
        else
        {
            cancel = true;
            System.Console.WriteLine ("No Score can be that high!");
        }
    }
}
//测试类
public class GameTest
{
    public static void Main ()
    {
        Game game = new Game ();
        Referee referee = new Referee (game);
        game.Score = 70;//【译注:输出 Good Score】
        game.Score = 110;// 【译注:输出 No Score can be that high!】
    }
}

时间: 2024-08-02 15:33:57

A Comparative Overview of C#中文版(一)的相关文章

A Comparative Overview of C#中文版(二)

中文 在GameTest里,我们分别创建了一个game和一个监视game的referee,然后,然后我们改变game的Score去看看referee对此有何反应.在这个系统里,game没有referee的任何知识,任何类都可以监听并对game的score变化产生反应.关键字event隐藏了除了+=和-=之外的所有委托方法.这两个操作符允许你添加(或移去)处理该事件的多个事件处理器.[译注:我们以下例说明后面这句话的意思:public class Game {public event ScoreC

A Comparative Overview of C#中文版(三)

中文 10.操作符重载     利用操作符重载机制,程序员可以创建让人感觉自然的好似简单类型(如int.long等等)的类.C#实现了一个C++操作符重载的限制版,它可以使诸如这样的精辟的例子-复数类操作符重载表现良好.     在C#中,操作符==是对象类的非虚的(操作符不可以为虚的)方法,它是按引用比较的.当你构建一个类时,你可以定义你自己的==操作符.如果你在集合中使用你的类,你应该实现IComparable接口.这个接口有一个叫CompareTo(object)方法,如果"this&qu

A Comparative Overview of C#中文版(四)

中文 当考虑到C++是怎么做的时候,Java是干了件好事,它简化了参数如何传递的问题.在C++中,方法[译注:C++中没有方法一说,应该称为"函数"或"成员函数"]的参数和方法调用通过传值.引用.指针[译注:例如int.int*.int&],使得代码变得不必要的复杂.C#显式传递引用,不管是方法声明时还是调用时.它大大地减少了混乱[译注:这句话应该这么理解:由于C++的语法问题,有时你并不知道你是在使用一个对象还是一个对象引用,本节后有示例],并达到了和Ja

Top Ten Traps in C# for C++ Programmers中文版(转)

c++|中文 [译序:C#入门文章.请注意:所有程序调试环境为Microsoft Visual Studio.NET 7.0 Beta2和 Microsoft .NET Framework SDK Beta2.限于译者时间和能力,文中倘有讹误,当以英文原版为准] 在最近发表于<MSDN Magazine>(2001年7月刊)上的一篇文章里,我讲了"从C++转移到C#,你应该了解些什么?".在那篇文章里,我说过C#和C++的语法很相似,转移过程中的困难并非来自语言自身,而是对

DotNet 资源大全中文版

原文:DotNet 资源大全中文版 转自:https://github.com/jobbole/awesome-dotnet-cn 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-dotnet 是由 quozd 发起和维护.内容包括:编译器.压缩.应用框架.应用模板.加密.数据库.反编译.IDE.日志.风格指南等. Awesome 系列虽然挺全,但基本只对收录的资源做了极为简要的介绍,如果有更详细的中文介绍,对相应开发者的帮助会更大.这

Flash 8 中文版视频教程(11)交集

教程|视频教程|中文 第 11 集:交集 课程要点:Flash 8 中文版视频教程,一共20集,带领您一起体验和学习 Flash 8 的新功能新特性! [全屏观看] | [下载视频] 本教程尺寸为 800 * 600 建议全屏在线观看或下载观看,以达到最佳观看效果

Java Persistence with Hibernate中文版Hibernate实战第2版出版

Java Persistence with Hibernate中文版Hibernate实战第2版出版 图灵出版社官方Hibernate实战(第2版)链接为: http://www.turingbook.com/Books/ShowBook.aspx?BookID=260 书 名: Hibernate实战(第2版) 评论星级: **** 书 号: 978-7-115-17448-2 原 书 名: Java Persistence with Hibernate 原出版社: Manning Publi

学习PHP技术:txtSQL安装手册中文版

txtsql的最大优点之一是文档很详细,可惜,我在网上找了半天也找不到中文版的文档,所以只好自己动手,利人利已吧,不过自己的E文水平自己是很清楚的,希望大家看了不会笑掉大牙才好,还希望大家多多指教. 欢迎使用txtSQL 2.2快速安装手册.这页将指引你如何开始安装txtSQL. 1-解压缩下载包 2-配置类文件 2.1-目录结构 3-包含类文件 3.1-类实例 3.2-连接到txtSQL 3.3- 更改密码 3.4-选择一个数据库 4-执行SQL指令 4.1-指令的列表 4.2-显示结果 5-

c++基础-C++ primer 中文版P461页

问题描述 C++ primer 中文版P461页 461页message类有一个地方不太明白: explicit Message(const std::string &str=""""): contents(str){} 这里加explicit属性是为什么呢?求大神指教^ ^谢谢 解决方案 显示构造函数,不要进行隐式转换,也就是编译器不会对你的对象赋值等情况进行类型转换,当你在不同类型赋值时,需要你代码明确指定, 解决方案二: 此处表明当其它类和Messag