博文
C#语言初级入门(3)(2006-09-03 18:01:00)
摘要:在这最后一个例子中,我们来看看C#的抽象和多态性。首先我们来定义一下这两个新的术语。抽象(Abstract)通过从多个对象提取出公共部分并把它们并入单独的抽象类中实现。在本例中我们将创建一个抽象类Shape(形状)。每一个形状都拥有返回其颜色的方法,不论是正方形还是圆形、长方形,返回颜色的方法总是相同的,因此这个方法可以提取出来放入父类Shape。这样,如果我们有10个不同的形状需要有返回颜色的方法,现在只需在父类中创建一个方法。可以看到使用抽象使得代码更加简短。
在面向对象编程领域中,多态性(Polymorphism)是对象或者方法根据类的不同而作出不同行为的能力。在下面这个例子中,抽象类Shape有一个getArea()方法,针对不同的形状(圆形、正方形或者长方形)它具有不同的功能。
下面是代码:
public abstract class Shape {
protected string color;
public Shape(string color) {
this.color = color;
}
public string getColor() {
return color;
}
public abstract double getArea();
}
public class Circle : Shape {
private double radius;
public Circle(string color, double radius) : base(color) {
this.radius = radius;
}
public override double getArea() {
return System.Math.PI * radius * radius;
}
}
public class Square : Shape {
private double sideLen;
public Square(string color, double sideLen) : base(color) {
this.sideLen = sideLen;
}
public override dou......
C#语言初级入门(2)(2006-09-03 18:00:00)
摘要:下面这个例子示范如何创建和使用用户定义的类以及如何创建动态链接库。利用文本编辑器创建两个文件。第一个是Apple.cs,内容如下:
public class Apple {
private string variety = "";
public Apple(string appleVariety) {
this.variety = appleVariety;
}
public void outputVariety() {
System.Console.WriteLine(variety);
}
}
第二个文件是Example2.cs,内容如下:
class Example2 {
static void Main() {
Apple mac = new Apple("Macintosh ");
Apple gra = new Apple("Granny Smith");
Apple cor = new Apple("Cortland");
mac.outputVariety();
gra.outputVariety();
cor.outputVariety();
}
}
首先,我们定义了一个新的用户定义类,名字为Apple。虽然Apple类并不一定要放到独立的文件中,但把每个类都放到自己独立的文件中是一个好的面向对象编程习惯,有助于简化组织和管理。我们为Apple类的声明加上了public修饰符(public class Apple),这样其他类就可以创建Apple类的实例。
下一行代码定义了实例变量variety。使用了修饰符private之后,只有在Apple类的内部才可以直接访问variety变量。这是一种常见的面向对象编程习惯,称为封装。封装之后,对象的工作细节对于对象的用户来说就隐藏不可见了。你现在正使用的键盘就是封装在现实世界中一个很好的例子。我们并不完全了解键击如何发送到控制器(我们之中的大多数都不知道),但只要理解它的接口如何运作就可以了。例如我们知道,打开文本编辑器,按下键盘上的“&”键,“&”字符就会出现在屏幕上。如果每一个人都必须了解键盘的工作细节而不是只要了解它的接口,我们之......
C#语言初级入门(1)(2006-09-03 18:00:00)
摘要:导读
C#是Microsoft开发的一种新语言,它和C/C++一样强大,和Java一样提供丰富的网络编程支持和自动内存管理,和VB一样简单易用。本文的目的是为尚未接触过C#的程序员介绍这种编程语言,是一个基础的入门教程。
作者:仙人掌工作室
2001-02-20
原文出处:http://journal.iftech.com/articles/0011_joey_CSharp/
C#读作“C sharp”,它是Microsoft开发的一种新语言,结合了C/C++的强大功能和Visual Basic的易用性。从最初的语言规范即可看出,C#无论在语法、丰富的Web开发支持还是自动化的内存管理上都和Java非常相似。因此,如果你曾经用过C++或者Java,再来学习C#应该是相当轻松的。
本文的目的在于为尚未接触过C#的程序员介绍这种编程语言。不论你以前是否用过C/C++或者Java,都可以从本文开始学习C#。本文的唯一假定是你具有某种类型的编程知识(如具有面向对象编程的经验则更好,但并非必须),并拥有某种类型的C#编译器。
最简单的C#程序
首先我们来看标准的Hello World程序。用文本编辑器创建一个新文件HelloWorld.cs,把下面的代码放入这个文件:
// 第一个c#程序
class HelloWorld {
static void Main() {
System.Console.WriteLine("Hello World!");
}
}
现在,在DOS命令窗口进入保存HelloWorld.cs的目录,然后执行:
csc HelloWorld.cs
该命令编译源代码并生成HelloWorld.exe文件。运行这个执行文件就可以看到:
Hello World!
下面我们来分析一下这个例子。第一行代码是一行注释,由“//”开始。和C/C++以及Java一样,“//”告诉编译器忽略该行直至结尾为止的内容。C#中的另外一种注释方法是块注释。块注释由“/*”开始,到“*/”结束。
程序中第二个重要的地方是第四行Main()方法的声明(static voi......
C#学习第十六天(2006-09-03 17:58:00)
摘要:7.3 引发异常
当你必须捕获异常时,其他人首先必须首先能够引发异常。而且,不仅其他人能够引发,你也可以负责引发。其相当简单:
throw new ArgumentException("Argument can't be 5");
你所需要的是throw 语句和一个适当的异常类。我已经从表7.1提供的清单中选出一个异常给这个例子。
表 7.1 Runtime提供的标准异常
异常类型 描述
Exception 所有异常对象的基类
SystemException 运行时产生的所有错误的基类
IndexOutOfRangeException 当一个数组的下标超出范围时运行时引发
NullReferenceException 当一个空对象被引用时运行时引发
InvalidOperationException 当对方法的调用对对象的当前状态无效时,由某些方法引发
ArgumentException 所有参数异常的基类
ArgumentNullException 在参数为空(不允许)的情况下,由方法引发
ArgumentOutOfRangeException 当参数不在一个给定范围之内时,由方法引发
InteropException 目标在或发生在CLR外面环境中的异常的基类
ComException 包含COM 类的HRESULT信息的异常
SEHException 封装win32 结构异常处理信息的异常
然而,在catch语句的内部,你已经有了随意处置的异常,就不必创建一个新异常。可能在表7.1 中的异常没有一个符合你特殊的要求——为什么不创建一个新的异常?在即将要学到小节中,都涉及到这两个话题。
7.3.1 重新引发异常
当处于一个catch 语句的内部时,你可能决定引发一个目前正在再度处理的异常,留下进一步的处理给一些外部的try-catch 语句。该方法的例子如 清单7.8所示。
清单 7.8 重新引发一个异常
1: try
2: {
3: checked
4: {
5: for (;nCurDig <= nComputeTo; nCurDig++)
6: nFactorial *= nCurDig;
7: }
C#学习第十五天(2006-09-03 17:57:00)
摘要:第七章 异常处理
通用语言运行时(CLR)具有的一个很大的优势为,异常处理是跨语言被标准化的。一个在C#中所引发的异常可以在Visual Basic客户中得到处理。不再有 HRESULTs 或者 ISupportErrorInfo 接口。尽管跨语言异常处理的覆盖面很广,但这一章完全集中讨论C#异常处理。你稍为改变编译器的溢出处理行为,接着有趣的事情就开始了:你处理了该异常。要增加更多的手段,随后引发你所创建的异常。
7.1 校验(checked)和非校验(unchecked)语句
当你执行运算时,有可能会发生计算结果超出结果变量数据类型的有效范围。这种情况被称为溢出,依据不同的编程语言,你将被以某种方式通知——或者根本就没有被通知。(C++程序员听起来熟悉吗?)
那么,C#如何处理溢出的呢? 要找出其默认行为,请看我在这本书前面提到的阶乘的例子。(为了方便其见,前面的例子再次在清单 7.1 中给出)
清单 7.1 计算一个数的阶乘
1: using System;
2:
3: class Factorial
4: {
5: public static void Main(string[] args)
6: {
7: long nFactorial = 1;
8: long nComputeTo = Int64.Parse(args[0]);
9:
10: long nCurDig = 1;
11: for (nCurDig=1;nCurDig <= nComputeTo; nCurDig++)
12: nFactorial *= nCurD......
C#学习第十四天(2006-09-03 17:56:00)
摘要:
当使用foreach时,只要注意一个问题:当确定循环变量的类型时,应该格外小心。选择错误的类型并没有受到编译器的检测,但它会在运行时受检测,且会引发一个异常。
6.2.3 while 语句
当你想执行一个内含语句0次或更多次时,while语句正是你所盼望的:
while (条件) 内含语句
条件语句——它也是一个布尔表达式 ——控制内含语句被执行的次数。你可以使用 break 和continue语句来控制while语句中的执行语句,它的运行方式同在for语句中的完全相同。
为了举例while的用法,清单 6.6 说明如何使用一个 StreamReader类输出C#源文件到屏幕。
清单 6.6 显示一个文件的内容
1: using System;
2: using System.IO;
3:
4: class WhileDemoApp
5: {
6: public static void Main()
7: {
8: StreamReader sr = File.OpenText ("whilesample.cs");
9: String strLine = null;
10:
11: while (null != (strLine = sr.ReadLine()))
12: {
13: Console.WriteLine(strLine);
14: }
15:
16: sr.Close();
17: }
18: }
代码打开文件 whilesample.cs, 接着当ReadLine 方法返回一个不等于null的值时,就在屏幕上显示所读取的值。注意,我在while条件语句中用到一个赋值。如果有更多的用&&和¦¦连接起来的条件语句,我不能保证它们是否会被执行,因为存在着“短路”的可能。
6.2.4 do 语句
C#最后可利用的循环语句是do语句。它与while语句十分相似,仅当经过最初的循环之后,条件才被验证。
do
{
内含语句
}
while (条件);
do语句保证内含语句至少被执行过一次,而且只要条件求值......
C#学习第十三天(2006-09-03 17:56:00)
摘要:何谓直达?在C(和C++)中,忽略break并且按以下编写代码是完全合法的:
nVar = 1
switch (nVar)
{
case 1:
DoSomething();
case 2:
DoMore();
}
在这个例子中,在执行了第一个case语句的代码后,将直接执行到其它case标签的代码,直到一个break语句退出switch语段为止。尽管有时这是一个强大的功能,但它更经常地产生难于发现的缺陷。
可如果你想执行其它case标签的代码,那怎么办? 有一种办法,它显示于清单6.3中。
清单 6.3 在swtich语句中使用 goto 标签 和 goto default
1: using System;
2:
3: class SwitchApp
4: {
5: public static void Main()
6: {
7: Random objRandom = new Random();
8: double dRndNumber = objRandom.NextDouble();
9: int nRndNumber = (int)(dRndNumber * 10.0);
10:
11: switch (nRndNumber)
12: {
13: case 1:
14: //什么也不做
15: break;
16: case 2:
17: goto case 3;
18: case 3:
19: Console.WriteLine("Handler for 2 and 3");
20: break;
21: case 4:
22: goto default;
23: // everything beyond a goto will be warned as
24: // unreachable code
25: default:
26: Console.WriteLine("Random number {0}", nRndNumber);
27: }
28: }
29: }
在这个例子中,通过Random类产生用于控制表达式的值(第......
C#学习第十二天(2006-09-03 17:55:00)
摘要:
第六章 控制语句
有一种语句,你在每种编程语言控制流程语句中都可以找到。在这一章中,我介绍了C#的控制语句,它们分为两个主要部分:
。选择语句
。循环语句
如果你是C或C++程序员,很多信息会让你感到似曾相似;但是,你必须知道它们还存在着一些差别。
6.1 选择语句
当运用选择语句时,你定义了一个控制语句,它的值控制了哪个语句被执行。在C#中用到两个选择语句:
。if 语句
。switch 语句
6.1.1 if 语句
最先且最常用到的语句是 if 语句。内含语句是否被执行取决于布尔表达式:
if (布尔表达式) 内含语句
当然,也可以有else 分枝,当布尔表达式的值为假时,该分支就被执行:
if (布尔表达式) 内含语句 else 内含语句
在执行某些语句之前就检查一个非零长字符串的例子:
if (0 != strTest.Length)
{
}
这是一个布尔表达式。(!=表示不等于。) 但是,如果你来自C或者C++,可能会习惯于编写象这样的代码:
if (strTest.Length)
{
}
这在C#中不再工作,因为 if 语句仅允许布尔( bool) 数据类型的结果,而字符串的Length属性对象返回一个整形(integer)。编译器将出现以下错误信息:
error CS0029: Cannot implicitly convert type 'int' to 'bool' (不能隐式地转换类型 'int' 为 'bool'。)
上边是你必须改变的习惯,而下边将不会再在 if 语句中出现赋值错误:
if (nMyValue = 5) ...
正确的代码应为
if (nMyValue == 5) ...
因为相等比较由==实行,就象在C和C++中一样。看以下有用的对比操作符(但并不是所有的数据类型都有效):
== ——如果两个值相同,返回真。
!= ——如果两个值不同,返回假。
<, <=, >, >= —— 如果满足了关系(小于、小于或等于、大于、大于或等于),返回真。
每个操作符是通过重载操作符被执行的,而且......
C#学习第十一天(2006-09-03 17:54:00)
摘要:5.5.3 存取修饰符
存取修饰符定义了某些代码对类成员(如方法和属性)的存取等级。你必须给每个成员加上所希望的存取修饰符,否则,默认的存取类型是隐含的。
你可以应用4个 存取修饰符之一:
public——任何地方都可以访问该成员,这是具有最少限制的存取修饰符。
protected——在类及所有的派生类中可以访问该成员,不允许外部访问。
private——仅仅在同一个类的内部才能访问该成员。甚至派生类都不能访问它。
internal——允许相同组件(应用程序或库)的所有代码访问。在.NET组件级别,你可以把它视为public,而在外部则为private。
为了演示存取修饰符的用法,我稍微修改了Triangle例子,使它包含了新增的域成员和一个新的派生类(见清单 5.13)。
清单 5.13 在类中使用存取修饰符
1: using System;
2:
3: internal class Triangle
4: {
5: protected int m_a, m_b, m_c;
6: public Triangle(int a, int b, int c)
7: {
8: m_a = a;
9: m_b = b;
10: m_c = c;
11: }
12:
13: public virtual double Area()
14: {
15: // Heronian formula
16: double s = (m_a + m_b + m_c) / 2.0;
17: double dArea = Math.Sqrt(s*(s-m_a)*(s-m_b)*(s-m_c));
18: return dArea;
19: }
20: }
21:
22: internal class Prism:Triangle
23: {
24: private int m_h;
25: public Prism(int a, int b, int c, int h):base(a,b,c)
26: {
27: m_h = h;
28: }
29:
30: public o......
C#学习第十天(2006-09-03 17:54:00)
摘要:
该类仅有一个方法,它允许我们触发事件。请注意,你必须进行事件域成员不为null的检测,因为可能会出现没有客户对事件感兴趣这种情况。
TestApp类包含了Main 方法,也包含了另外两个方法,它们都具备事件所必需的信号。其中一个方法是静态的,而另一个是实例方法。
EventSource 被实例化,而静态方法CatchEvent被预关联上了 TextOut事件:
evsrc.TextOut += new EventHandler(CatchEvent);
从现在起,当事件被触发时,该方法被调用。如果你对事件不再感兴趣,简单地取消关联:evsrc.TextOut -= new EventHandler(CatchEvent);
注意,你不能随意取消关联的处理函数——在类代码中仅创建了这些处理函数。为了证明事件处理函数也和实例方法一起工作,余下的代码建立了TestApp 的实例,并钩住事件处理方法。
事件在哪方面对你特别有用?你将经常在ASP+中或使用到WFC (Windows Foundation Classes)时,涉及到事件和代表元。
5.5 应用修饰符
在这一章的学习过程中,你已经见过了象public、virtual等修饰符。欲以一种易于理解的方法概括它们,我把它们划分为三节:
。类修饰符
。成员修饰符
。存取修饰符
5.5.1 类修饰符
到目前为止,我还没有涉及到类修饰符,而只涉及到了应用于类的存取修饰符。但是,有两个修饰符你可以用于类:
abstract——关于抽象类的重要一点就是它不能被实例化。只有不是抽象的派生类才能被实例化。派生类必须实现抽象基类的所有抽象成员。你不能给抽象类使用sealed 修饰符。
sealed——密封 类不能被继承。使用该修饰符防止意外的继承,在.NET框架中的类用到这个修饰符。
要见到两个修饰符的运用,看看清单5.12 ,它创建了一个基于一个抽象类的密封类(肯定是一个十分极端的例子)。
清单 5.12 抽象类和密封类
1: using System;
2:
3: abstract class AbstractClass
4: {
5: abstract public void MyMethod();
6: }
7: <......