c#技术大讨论!大家有什么看法,中文或E文都可以发表!(300分)

  • 主题发起人 主题发起人 danie
  • 开始时间 开始时间
C#是什么东东?
我想知道.
 
技術前言有,你可以參考!
 
C#,吾辈程序员又多了一个类似于 Java 玩具。
 
已经有写文章出来了,但我还没用过
 
吾孤陋寡闻,请不吝赐教!
 
c#的主设是原turbo pascal 和delphi 的领导人
 
M$向来比较大吹大擂的,看看介绍还可以,不过要等到真正成熟,恐怕。。。
 
<a href="http://www.delphibbs.com/delphibbs/DispQ.asp?LID=448759"> http://www.delphibbs.com/delphibbs/DispQ.asp?LID=448759</a>
 
同意djdsz的看法,c#可能又是象vJ++之类的不伦不类的东西,当心上当,
还是安安心心喝咖啡吧
 
C#是很类似Java的东东!
可选择安全或不安全(指针),可生出exe但要 .net FrameWork SDK支持。
 
向前沿高手学习
 
学习学习
 
C#是一个注定要脱颖而出的语言,理由:
1、M$想做的事几乎没有不成功的;
2、.NET的系统架构的确先进、科学;
我也正在学这个东西,准备装一个VS.NET,有问题大家可以一起讨论!
另外建议yysun开设.NET专栏!!!
 
很多人说C#是微软用来和Java抗衡的武器,因为二者在很大程度上有着惊人的相似,尽管如此,两者不同的地方也很多,所谓“于细微处见差异”。那么两者的相似和区别都在什么地方呢?我们从今天开始,会从各个角度来对比C#和Java的特点,希望能对正在学习、使用C#的朋友有所帮助。
1、C#和.NET平台的概貌
  2000年6月,微软发布C#语言和.NET平台。C#语言是一种强类型的,面向对象的语言,它具有语法简单、表达力强的特点,而.NET平台则是构成微软的“.NET计划”的基石。
  .NET平台的核心包括两方面,一方面就是著名的通用语言运行机(Common Language Runtime),虽然这个名词起得晦涩了点,不过大家可以拿它和Java的虚拟机来作比较,二者完成的任务大致相同;另一方面就是一大堆通用函数库,这些库函数可以被多种语言调用,并且通过编译都产生一种共同的中间语言(Intermediate Language),这种语言也可以拿Java的字节码来类比,虽然完成的方式有些不一样。
2、C#和Java
  下面简单地把C#和Java的相似处列出来,虽然在这里我们重点讨论的是C#和Java的不同点,但是了解一下二者的相同之处也是很有必要的。
  二者都编译成跨平台的、跨语言的代码,并且代码只能在一个受控制的环境中运行
  自动回收垃圾内存,并且消除了指针(在C#中可以使用指针,不过必须注明unsafe关键字)
  都不需要头文件,所有的代码都被“包(package)”限制在某个范围内,并且因为没有头文件,所以消除了类定义的循环依赖
  所有的类都是从对象派生出来,并且必须使用New关键字分配内存
  用对象加锁的方式来支持多线程
  都具有接口(interface)的概念
内部类
  继承类的时候不会以某种特定的访问权限来继承;
  没有全局函数或者常量,一切必须属于类;
  数组或者字符串都自带长度计算和边界检查;
  只使用“.”操作符,没有“->”和“::”;
  “null”、“boolean”和“bool”成为了关键字;
  任何变量均在使用前进行初始化;
  不能使用整数来返回到if条件语句中,必须使用布尔值;
  “Try”模块后可以有“finally” ;
3. 属性(Property)
  属性的概念对大家来说应该是很熟悉的,类成员函数可以自由地访问本类中的任何属性成员。不过若要从一个类中去访问另一个类中的属性,那就比较麻烦了,所以很多时候我们使用Getxxx和Setxxx方法,这样看起来显得极不自然,比如用Java或者C++,代码是这样的:
  foo.setSize (getSize () + 1);
  label.getFont().setBold (true);
  但是,在C#中,这样的方法被“属性化”了。同样的代码,在C#就变成了:
  foo.size++;
  label.font.bold = true;
  可以看出来,C#显然更容易阅读和理解。我们从这个“属性方法”的子程序代码中,也可以看到类似情况:
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#中把属性成员称作“域(field)”,而“属性”则成为这种“属性化的方法”专用的名词。顺便说一句,其实这样的属性化方法在VB和DELPHI中是经常碰到的,在VB中它也就叫属性。
  另外,在C#中Get和Set必须成对出现,一种属性不能只有Get而没有Set(在Java和C++中就可以只有Get或者只有Set),C#中这样做的好处在于便于维护,假如要对某种属性进行修改,就会同时注意Get和Set方法,同时修改,不会改了这个忘了那个。
4、对象索引机制(Indexer)
  C#中引入了对象索引机制。说得明白点,对象索引其实就是对象数组。这里和上一节中的属性联系起来讲一下,属性需要隐藏Get和Set方法,而在索引机制中,各个对象的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", ...);
  呵呵,有了这种特性,我们就再不用怕课堂上老师叫我们写对象数组这种程序了。
5. 指代(Delegate)
  指代这个玩意很特别,它有点象指针,但又不完全是,不过大家还是可以把它理解为一种类型安全的、面向对象的指针。(什么是类型安全和面向对象就不用讲了吧?)顺便提一句,有很多书上把Delegate翻译成代理,我觉得这样翻不够确切,翻译成“指代”更恰当些,道理上吻合,并且还符合它的本来意思——微软本来就是用Delegate来“取代指针”,所以叫“指代”,呵呵。
  说起指代,也许至今Sun还会对它愤愤不已,为什么呢?因为在Sun的标准Java中是没有这个东西的,它是微软99年发布的MSVJ++6添加的“新特性”。为此,两家公司吵得不亦乐乎,并且还专门在网上写了大量文章互相攻击,有兴趣的朋友可以去看看(只有英文版)。
http://www.Javasoft.com/docs/white/delegates.html
http://msdn.microsoft.com/visualj/technical/articles/delegates/truth.asp
  话归正传,指代有什么特点呢?一个明显的特点就是它具有了指针的行为,就好象从Java又倒回到了C++。在C#中,指代完成的功能大概和C++里面的指针,以及Java中的接口相当。但是,指代比起C++的“正宗指针”来又要高明一些,因为它可以同时拥有多个方法,相当于C++里面的指针能同时指向多个函数,并且是类型安全的,这一点体现了它的“对象”特性;而比起Java的接口来,指代高明的地方在于它能可以不经过内部类就调用函数,或者用少量代码就能调用多种函数,这一点体现了它的“指针”特性。呵呵,很有“波粒二象性”的味道吧?指代最重要的应用在于对于事件的处理,下一节我们将重点介绍。
6、事件(Event)
  C#对事件是直接支持的(这个特点也是MSVJ所具有的)。当前很多主流程序语言处理事件的方式各不相同,Delphi采用的是函数指针(这在Delphi中的术语是“closure”)、Java用改编类来实现、VC用WindowsAPI的消息系统,而C#则直接使用delegate和event关键字来解决这个问题。下面让我们来看一个例子,例子中会给大家举出声明、调用和处理事件的全过程。

//首先是指代的声明,它定义了唤醒某个函数的事件信号
public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel);
//定义一个产生事件的类
public class Game
{
 // 注意这里使用了event关键字
 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.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;
  game.Score = 110;
 }
}
  在主函数中,我们创建了一个game对象和一个裁判对象,然后我们通过改变比赛分数,来观察裁判对此会有什么响应。
  请注意,我们的这个系统中,Game对象是感觉不到裁判对象的存在的,Game对象在这里只负责产生事件,至于有谁会来倾听这个事件,并为之作出反应,Game对象是不作任何表态的。
  我们注意到,在裁判类的Referee函数中,Game.ScoreChange后面使用了+=和-=操作符,这是什么意思呢?回到我们定义ScoreChange的地方,可以发现ScoreChange是用event关键字修饰的,那么这里的意思就很明白了:ScoreChange是一个事件,而事件被触发后需要相应的事件处理机制,+=/-=就是为这个事件增加/移除相对应的事件处理程序,而且,并不是一个事件只能对应一个处理程序,我们还可以用这两个操作符为同一事件增加/移除数个事件处理程序。怎么样?很方便吧!
  在实际应用中,和我们上面讲的(竞赛-裁判)机制很相近的系统就是图形用户界面系统了。Game对象可以看作是图形界面上的小零件,而得分事件就相当于用户输入事件,而裁判就相当于相应的应用程序,用于处理用户输入。
  指代机制的首次亮相是在MSVJ里,它是由Anders Hejlsberg发明的,现在又用到了C#中。指代用在Java语言中的后果,则直接导致了微软和Sun之间对类和指针的关系产生了大量的争论和探讨。有意思的是,Java的发明者James Gosling非常幽默地称呼指代的发明者Anders Hejlsberg为“‘函数指针’先生”,因为Anders Hejlsberg总是想方设法地把指针变相地往各种语言中放;不过有人在看了Java中大量地使用了各种类后,也戏称Java的发明者James Gosling为“‘全都是类’先生”,真是其中滋味,尽在不言中啊。
 
C#语言自C/C++演变而来。但是,它现代、简单、完全面向对象和类型安全。
如果您是C/C++程序员,学习曲线将会很平坦。许多C#语句直接借用您所喜爱的语言,
包括表达式和操作符。假如不仔细看,简直会把它当成C++。
关于C#最重要的一点:它是现代的编程语言。它简化和现代化了C++在类、
名字空间、方法重载和异常处理等领域。屏弃了C++的复杂性,使它更易用、
更少出错。
对C#的易用有贡献的是减少了C++的一些特性,不再有宏、模板和多重继承。
特别对企业开发者来说,上述功能只会产生更多的麻烦而不是效益。
使编程更方便的新功能是严格的类型安全、版本控制、垃圾收集(garbage
collect)等等。所有的这些功能的目标都是瞄准了开发面向组件的软件。
在继续呈现出更多的功能之前,我想停下来并在下面说明C#至关重要的各种要素。
简单
现代
面向对象
类型安全
版本控制
兼容
灵活

简单
C#具有C++所没有的一 个优势就是学习简单。该语言首要的目标就是简单。
很多功能(还不如说是缺少了C++的一些功能)有助于C#全方位的简单。
在C#中,没有C++中流行的指针。默认地,您工作在受管理的代码中,
在那里不允许如直接存取内存等不安全的操作。我想没有C++程序员可以声称,
从没有使用指针访问过不属于他们的内存。
与指针"戏剧性"密切相关的是"愚蠢的"操作。在C++中,有::、.、和->操作符,
它们用于名字空间、成员和引用。对于新手来说,操作符至今仍是学习的一道难关。C#弃用其它操作符,仅使用单个操作符 "."。现在一个程序员所需要理解的就是嵌套名字的注解了。
您不必记住基于不同处理器架构的隐含的类型,甚至各种整型的变化范围。
C#使用统一的类型系统,屏弃了C++多变的类型系统。这种系统充许您把各种类型
作为一个对象查看,它是一个原始类型还是一个full-blown 类。和其它编程语言相比,由于加框(boxing)和消框(unboxing)的机制,把简单类型当作对象处理并不能获得性能的改善。稍后将详细解释加框和消框,但基本上仅当需要时才使用对象访问简单类型这种技术。
首先,老练的程序员可能不喜欢它,但是整型和布尔型如今终归是两种完全不同的
数据类型。这就意味着原来if语句中错误的赋值现在会被编译出错,因为if语句只
接受布尔类型的值。再也不会出现误用赋值符为比较符这样的错误!
C#同时也解决了存在于C++中已经有些年头的多余东西(redundancies)。这种多余
包括常数预定义,不同字符类型等。鉴于多余表单已经从该语言中消失,故一般在C#中
都可以使用表单了。
现代
您投入学习C#的努力是一笔大投资,因为C#是为编写NGWS 应用程序的主要语言而设计。
您 将会发现很多自己用C++可以实现或者很费力实现的功能,在C#中不过是一部分
基本的功能而已。
对于企业级的编程语言来说,新增的金融数据类型很受欢迎。您用到了一种新的
十进制数据类型,它专用于金融计算方面。如果不喜欢这种现成简单的类型,
根据您应用程序的特殊需求,可以很容易地创建出新的一种数据类型。
我已经提到,指针不再是您编程武器的一部分。不要太惊讶,全面的内存管理已经
不是您的任务。运行时NGWS提供了一个垃圾收集器,负责C#程序中的内存管理。
因内存和应用程序都受到管理,所以很必要增强类型安全,以确保应用的稳定性。
对于C++程序员,异常处理的切不是新的东西,但它是C#的主要功能。C#的异常处理
与C++的不同点在于它是交叉语言的(运行时的另一个功能)。在没有C#之前,您必须
处理怪异的HRESULTs,但现在由于使用了基于异常的健壮的出错处理, 这一切都 结束了。
对于现代的应用程序,安全是首要的,C#也不会例外。它提供了元数据语法,用于
声明下述NGWS安全模式的能力和许可。元数据是NGWS运行时的一个关键的概念,
下一章将涉及到它更深的含义。
面向对象
您不会预料一种新语言不支持面向对象的功能吧? C#当然支持所有关键的面向对象的概念,
如封装、继承和多态性。完整的C#类模式构建在NGWS运行时的虚拟对象系统(VOS,
Virtual Object System)的上层,VOS将在下章描述。对象模式只是基础的一部分,
不再是编程语言的一部分。
您一开始必须关注的事,就是不再有全局函数、变量或者是常量。所有的东西都封装
在类中,包括事例成员(通过类的事例--对象可以访问)或都静态成员(通过数据类型)。
这些使C#代码更加易读且有助于减少潜在的命名冲突。
定义类中的 方法默认是非虚拟的(它们不能被派生类改写)。主要论点是,这样会消除
由于偶尔改写方法而导致另外一些原码出错。要改写方法,必须具有显式的虚拟标志。
这种行为不但缩减速了虚拟函数表,而且还确保正确版本的控制。
使用C++编写类,您可以使用访问权限(access modifiers) 给类成员设置不同的访问
等级。C#同样支持private、protected 和public 三种访问权限 ,而且还增加了第四种
:internal。有关访问权限 的详细情况将在第五章 "类" 中说明。
您曾经创建了多少个类是从多基类派生出来的(ATL 程序员,您的投票不计在内!) ?
大多数情况,仅需从一个类派生出。多基类惹出的麻烦通常比它们解决的问题还多。
那就是为什么C#仅允许一个基类。如果您觉得需要多重继承,可以运用接口。
一个可能出现的问题:在C#中不存在指针,如何模仿它? 这个问题的答案很有代表性,
它提供了对NGWS运行时事件模式的支持。再次,我将把对它的全面解释放到第五章。
类型安全
我再次选指针作为一个例子。在C++中拥有一个指针,您能自由地把它强制转换成为
任何类型,包括干出诸如把一个int*(整型指针)强制转换成一个double *(双精度指针)
这样的傻事。只要内存支持这种操作,它就"干过"。这并不是您所想象的企业级编程语言
的类型安全。
纲要性的问题,,C#实施最严格的类型安全,以保护自己及垃圾收集器(garbage
collector)。所以必须遵守C#中一些相关变量的规则:
您 不能使用没有初始化的变量。对于对象的成员变量,编译器负责清零。而局部变量,
则由您负责清零。当您使用一个没有初始化的变量时,编译器会教您怎么做。
优点是能够避免由于使用不经初始化的变量计算结果而导致的错误,而您还不知道
这些奇怪的结果是如何产生的。
C#取消了不安全的类型转换。不能把一个整型强制转换成一个引用类型(如对象),
而当向下转换时,C#验证这种转换是正确的。(也就是说,派生类真的是从向下转换
的那个类派生出来的。)
边界检查是C#的一部分。再也不会出现这种情况:当数组实际只定义了n-1个元素,
却超额地使用了n个元素。
算术运算有可能溢出终值数据类型的范围。C#允许在语句级或应用程序级检测这些运算。
在允许检测溢出的情况下,当溢出发生时将会抛出一个异常。
在C#中,被传递的引用参数是类型安全的。
版本可控(Versionable)
在过去的几年中,几乎所有的程序员都至少有一次不得不涉及到众所周知的"DLL地狱"。
该问题起因于多个应用程序都安装了相同DLL名字的不同版本。有时,老版本的应用程序
可以很好地和新版本的DLL一起工作,但是更多的时候它们会中断运行。现在的版本问题
真是令人头痛。
就象您将在第八章"用C#写组件"所看到的,NGWS runtime 将对您所写的应用程序提供版
本支持。C#可以最好地支持版本控制。尽管C#不能确保正确的版本控制,但是它可以为
程序员保证版本控制成为可能。有这种支持,一个开发人员就可以确保当他的类库升级时,
仍保留着对已存在的客户应用程序的二进制兼容。
兼容
C#并没有存在于一个封闭的世界中。它允许使用最先进的NGWS的通用语言规定(Common
Language Specification,简写为CLS)访问不同的API。CLS规定了一个标准,用于符合
这种标准的语言的内部之间的操作。为了加强CLS的编译,C#编译器检测所有的公共出口
编译,并在通不过时列出错误。
当然,您也想能够访问旧一点的COM对象。NGWS运行时提供对COM透明的访问。如何集成
原来的代码将在第10章"非管理代码的内部操作"有介绍。
OLE 自动化是一种特殊的动物。任一个使用C++创建OLE自动化项目的人已经喜欢上各种
各样的自动化数据类型。有个好消息就是C#支持它们,而没有烦锁的细节。
最后,C#允许您 用C 原型的API进持内部操作。可以从您的应用程序访问任何DLL中的
入口点(有C的原型)。用于访问原始API的功能称作平台调用服务(Plaform Invocation
Services ,缩写PInovke),第10章将展示使用C API进行内部操作的一些例子。
灵活
上一部分的最后一段有可能提醒了程序员。您可能会问:"难道就没有我要传递指针的
API吗?" 您是正确的。不是仅有少数的这种API,而是很多(有点保守的估计)。这种对
原始WIN32代码的访问有时导致对非安全类指定指针的使用(尽管它们中的一些由于受
COM和PInvoke的支持可以解决)。
尽管C#代码的缺省状态是类型安全的,但是您可以声明一些类或者仅声明类的的方法
是非安全类型的。这样的声明允许您使用指针、结构,静态地分配数组。安全码和非安全
码都运行在同一个管理空间,这样暗示着当从安全码调用非安全码时不会陷入
列集(marshaling)。

C#语言从C和C++演变而来,它是给那些愿意牺牲C++一点底层功能,以获得更方便和更产
品化的企业开发人员而创造的。C#现代、简单、面向对象和类型安全。尽管它借鉴了C和
C++的许多东西,但是在一些诸如名字空间、类、方法和异常处理等特定领域,它们之间
还存在着巨大的差异。
C#为您提供了方便的功能,如垃圾收集、类型安全、版本控制,等等。仅有的"代价"就是,
代码操作默认是类型安全的,不允许指针。光是类型安全就可以搞定了。但是,如果您
需要指针,仍可以通过非安全码使用它们,而且当调用非安全码时,不能含有列集。
 
很多人说C#像C++,其实那是因为他们没用过Delphi,其实C#更像Delphi,
包括“属性”,“事件”等等,我看过一个Microsoft提供的C#的例子代码,
里面一个类的函数参数居然是: funcabc(Object sender, ....)
太熟悉了不是?!
 
不知那里有关于C#的资料
 
后退
顶部