博文

C# 语言规范--1.9 接口(2006-09-03 18:31:00)

摘要:一个接口定义一个协定。实现接口的类或结构必须遵守其协定。接口可以包含方法、属性、索引器和事件作为成员。 示例interface IExample { string this[int index] { get; set; } event EventHandler E; void F(int value); string P { get; set; } } public delegate void EventHandler(object sender, EventArgs e); 显示了一个包含索引器、事件 E、方法 F 和属性 P 的接口。 接口可以使用多重继承。在下面的示例中,interface IControl { void Paint(); } interface ITextBox: IControl { void SetText(string text); } interface IListBox: IControl { void SetItems(string[] items); } interface IComboBox: ITextBox, IListBox {} 接口 IComboBox 同时从 ITextBox 和 IListBox 继承。 类和结构可以实现多个接口。在下面的示例中,interface IDataBound { void Bind(Binder b); } public class EditBox: Control, IControl, IDataBound { public void Paint() {...} public void Bind(Binder b) {...} } 类 EditBox 从类 Control 派生,并且同时实现 IControl 和 IDataBound。 在前面的示例中,IControl 接口中的 Paint 方法和 IDataBound 接口中的 Bind 方法是使用 EditBox 类的公共成员实现的。C# 提供了另一种方式来实现这些方法,使得实现类避免将这些成员设置成公共的。这就是:接口成员可以用限定名来实现。例如,在 EditBox 类中将 Paint 方法命名为 ......

阅读全文(1247) | 评论:0

C# 语言规范--1.8 结构(2006-09-03 18:30:00)

摘要:类与结构有很多相似之处:结构可以实现接口,并且可以具有与类相同的成员类型。然而,结构在几个重要方面不同于类:结构为值类型而不是引用类型,并且结构不支持继承。结构的值存储在“在堆栈上”或“内联”。细心的程序员有时可以通过聪明地使用结构来增强性能。 例如,将 Point 定义为结构而不是类在运行时可以节省很多内存空间。下面的程序创建并初始化一个 100 点的数组。对于作为类实现的 Point,出现了 101 个实例对象,因为数组需要一个,它的 100 个元素每个都需要一个。class Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } class Test { static void Main() { Point[] points = new Point[100]; for (int i = 0; i < 100; i++) points[i] = new Point(i, i*i); } } 如果将 Point 改为作为结构实现,如struct Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } 则只出现一个实例对象(用于数组的对象)。Point 实例在数组中内联分配。此优化可能会被误用。使用结构而不是类还会使应用程序运行得更慢或占用更多的内存,因为将结构实例作为值参数传递会导致创建结构的副本。  ......

阅读全文(1349) | 评论:0

C# 语言规范--1.7 类(2006-09-03 18:30:00)

摘要:类声明定义新的引用类型。一个类可以从另一个类继承,并且可以实现多个接口。 类成员可以包括:常数、字段、方法、属性、事件、索引器、运算符、实例构造函数、析构函数、静态构造函数和嵌套类型声明。每个成员都有关联的可访问性,它控制能够访问该成员的程序文本区域。有五种可能的可访问性形式。下表概述了这些形式。 形式 直观含义 public 不限制访问。 protected 访问限于该成员所属的类或从该类派生来的类型。 internal 访问限于此程序。 protected internal 访问限于此程序或从该成员所属的类派生的类型。 private 访问限于该成员所属的类型。 示例using System; class MyClass { public MyClass() { Console.WriteLine("Instance constructor"); } public MyClass(int value) { MyField = value; Console.WriteLine("Instance constructor"); } ~MyClass() { Console.WriteLine("Destructor"); } public const int MyConst = 12; public int MyField = 34; public void MyMethod(){ Console.WriteLine("MyClass.MyMethod"); } public int MyProperty { get { return MyField; } set { MyField = value; } } public int this[int index] { get { return 0; } set { Console.WriteLine("t......

阅读全文(1289) | 评论:0

C# 语言规范--1.6 语句(2006-09-03 18:30:00)

摘要:C# 中的大多数语句都是直接从 C 和 C++ 借用的,但有一些值得注意的添加和修改。下表列出了可用的语句类型,并提供了每种类型的示例。 语句 示例 语句列表和块语句 static void Main() { F(); G(); { H(); I(); } } 标记语句和 goto 语句 static void Main(string[] args) { if (args.Length == 0) goto done; Console.WriteLine(args.Length); done: Console.WriteLine("Done"); } 局部常数声明 static void Main() { const float pi = 3.14f; const int r = 123; Console.WriteLine(pi * r * r); } 局部变量声明 static void Main() { int a; int b = 2, c = 3; a = 1; Console.WriteLine(a + b + c); } 表达式语句 static int F(int a, int b) { return a + b; } static void Main() { F(1, 2); // Expression statement } if 语句 static void Main(string[] args) { if (args.Length == 0) Console.WriteLine("No args"); else Console.WriteLine("Args"); } switch 语句 static void Main(string[] args) { switch (args.Length) { case 0: ......

阅读全文(1178) | 评论:0

C# 语言规范--1.5 表达式(2006-09-03 18:29:00)

摘要:C# 包含一元运算符、二元运算符和一个三元运算符。下表概述了这些运算符,并将它们按优先级以从高到低的顺序列出: 章节 类别 运算符 第 7.5 节 基本 x.y f(x) a[x] x++ x-- new typeof checked unchecked 第 7.6 节 一元 + - ! ~ ++x --x (T)x 第 7.7 节 乘法 * / % 第 7.7 节 加法 + - 第 7.8 节 移位 << >> 第 7.9 节 关系和类型检测 < > <= >= is as 第 7.9 节 相等 == != 第 7.10 节 逻辑 AND & 第 7.10 节 逻辑 XOR ^ 第 7.10 节 逻辑 OR | 第 7.11 节 条件 AND && 第 7.11 节 条件 OR || 第 7.12 节 条件 ?: 第 7.13 节 赋值 = *= /= %= += -= <<= >>= &= ^= |= 当表达式包含多个运算符时,运算符的优先级控制各运算符的计算顺序。例如,表达式 x + y * z 按 x + (y * z) 计算,因为 * 运算符具有的优先级比 + 运算符高。 当操作数出现在具有相同优先级的两个运算符之间时,运算符的顺序关联性控制运算的执行顺序: 除了赋值运算符外,所有的二元运算符都向左顺序关联,意思是从左向右执行运算。例如,x + y + z 按 (x + y) + z 计算。 赋值运算符和条件运算符 (?:) 向右顺序关联,意思是从右向左执行运算。例如,x = y = z 按 x = (y = z) 计算。 优先级和顺序关联性都可以用括号控制。例如,x + y * z 先将 y 乘以 z 然后将结果与 x 相加,而 (x + y) * z 先将 x 与 y 相加,然后再将结果乘以 z。  ......

阅读全文(1312) | 评论:0

C# 语言规范--1.4 自动内存管理(2006-09-03 18:28:00)

摘要:手动内存管理要求开发人员管理内存块的分配和回收。手动内存管理可能既耗时又麻烦。在 C# 中提供了自动内存管理,使开发人员从这个繁重的任务中解脱出来。在绝大多数情况下,自动内存管理可以提高代码质量和开发人员的工作效率,并且不会对表达能力或性能造成负面影响。 示例using System; public class Stack { private Node first = null; public bool Empty { get { return (first == null); } } public object Pop() { if (first == null) throw new Exception("Can't Pop from an empty Stack."); else { object temp = first.Value; first = first.Next; return temp; } } public void Push(object o) { first = new Node(o, first); } private class Node { public Node Next; public object Value; public Node(object value): this(value, null) {} public Node(object value, Node next) { Next = next; Value = value; } } } 显示了一个 Stack 类,它实际上是 Node 实例的一个链接表。Node 实例是在 Push 方法中创建的,当不再需要它们时会对其进行垃圾回收。当任何代码都不再可能访问某个 Node 实例时,该实例就成为垃圾回收的对象。例如,当从 Stack 中移除某项时,相关的 Node 实例就符合了垃圾回收条件,等......

阅读全文(1125) | 评论:0

C# 语言规范--1.3 变量和参数(2006-09-03 18:28:00)

摘要:变量表示存储位置。每个变量都属于一种类型,它确定什么样的值可以存储在该变量中。局部变量是在方法、属性或索引器中声明的变量。局部变量是通过指定类型名称和声明符(它指定变量名和可选的初始值)定义的,如:int a; int b = 1; 但局部变量声明也可以包含多个声明符。a 和 b 的声明可以重写为:int a, b = 1; 一个变量必须先赋值,然后才能使用它的值。示例class Test { static void Main() { int a; int b = 1; int c = a + b; // error, a not yet assigned ... } } 导致编译时错误,因为它试图在给变量 a 赋值之前使用它。 字段是与类或结构或与类或结构的实例关联的变量。用 static 修饰符声明的字段定义静态变量,不用此修饰符声明的字段则定义实例变量。静态字段与类型关联,而实例变量与实例关联。示例using Personnel.Data; class Employee { private static DataSet ds; public string Name; public decimal Salary; ... } 显示了具有一个私有静态变量和两个公共实例变量的 Employee 类。 形参声明也定义变量。有四种类型的参数:值参数、引用参数、输出参数和参数数组。 值参用于“in”参数传递。在此过程中,自变量的值被传入方法中。因为一个值参在方法中用自己的变量存储(而非原自变量),所以对此参数的修改不会影响到原自变量。值参的变量是通过复制原自变量的值来初始化的。示例using System; class Test { static void F(int p) { Console.WriteLine("p = {0}", p); p++; } static void Main() { int a = 1; Console.WriteLine("pre: a = {0}", a); F(a); Console.Writ......

阅读全文(1405) | 评论:0

C# 语言规范--1.2 类型(2006-09-03 18:27:00)

摘要:C# 支持两种类型:“值类型”和“引用类型”。值类型包括简单类型(如 char、int 和 float)、枚举类型和结构类型。引用类型包括类 (Class) 类型、接口类型、委托类型和数组类型。 值类型与引用类型的区别在于值类型的变量直接包含其数据,而引用类型的变量则存储对象引用。对于引用类型,两个变量可能引用同一对象,因此对一个变量的操作可能影响另一个变量所引用的对象。对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响另一个变量。 示例using System; class Class1 { public int Value = 0; } class Test { static void Main() { int val1 = 0; int val2 = val1; val2 = 123; Class1 ref1 = new Class1(); Class1 ref2 = ref1; ref2.Value = 123; Console.WriteLine("Values: {0}, {1}", val1, val2); Console.WriteLine("Refs: {0}, {1}", ref1.Value, ref2.Value); } } 显示了这种区别。运行该程序,可见下列输出:Values: 0, 123 Refs: 123, 123 给局部变量 val1 赋值不会影响局部变量 val2,这是因为两个局部变量都是值类型(int 类型),每个局部变量都保存着各自的数据。相反,赋值 ref2.Value = 123; 则会影响到 ref2,因为 ref1 和 ref2 所引用的其实是同一个对象。 应对代码行Console.WriteLine("Values: {0}, {1}", val1, val2); Console.WriteLine("Refs: {0}, {1}", ref1.Value, ref2.Value); 做进一步解释,因为方法 Console.WriteLine 的某些字符串格式化行为较复杂,它所需的参数数目是可变的。第一个参数是字符串,它可能包含类似 {0......

阅读全文(1041) | 评论:0

C# 语言规范--1.1 开始(2006-09-03 18:26:00)

摘要:经典性“hello, world”程序可以写为:using System; class Hello { static void Main() { Console.WriteLine("hello, world"); } } C# 程序的源代码通常存储在一个或多个以 .cs 为文件扩展名的文本文件(如 hello.cs)中。可以通过 Visual Studio .NET 所提供的命令行编译器,使用以下命令行指令来编译此程序:csc hello.cs 它产生一个名为 hello.exe 的应用程序。当此应用程序运行时,它产生的输出是:hello, world 仔细观察此程序可以发现: “using System;”指令引用一个名为 System 的命名空间,它由 Microsoft .NET Framework 类库定义。此命名空间包含 Main 方法中引用的 Console 类。命名空间提供了一种分层方法来组织一个或多个程序中的各种元素。用“using”指令指定一个命名空间后,该命名空间中的所有成员均可直接被引用。所以,在“hello, world”程序中,可直接使用 Console.WriteLine(而不必使用 System.Console.WriteLine)。 Main 方法是 Hello 类的成员。它具有 static 修饰符,因此 Main 方法是相对于类 Hello 本身而不是相对于此类的实例。 应用程序的入口点(即当程序开始运行时首先被调用的方法)总是名为 Main 的静态方法。 “hello, world”输出依靠类库实现。C# 语言本身不提供类库,它使用公共的类库(Visual Basic .NET 和 Visual C++ .NET 也使用它)。 对 C 和 C++ 开发人员而言,值得注意的是一些“没有”出现在“hello, world”程序中的东西。 该程序中的 Main 方法不是全局的。C# 不支持全局级别的方法和变量;这类元素总是包含在类型声明(如类声明和结构声明)中。 该程序没有使用“::”运算符和“->”运算符。在 C# 中,“::”根本不是运算符,而“->”运算符仅在一小部分程序中使用,即那些涉及不安全代码的程序。分隔符“.”在复合名称中使用,如......

阅读全文(1214) | 评论:0

C# 程序员参考--OLE DB 教程(2006-09-03 18:26:00)

摘要:OLE DB 是用于访问数据的基于 COM 的应用程序编程接口 (API)。OLE DB 支持访问以 OLE DB 提供程序可以使用的任何格式(数据库、电子表格、文本文件等)存储的数据。每个 OLE DB 提供程序从某一特定类型的数据源(例如 SQL Server 数据库、Microsoft Access 数据库或 Microsoft Excel 电子表格)公开数据。 本教程说明如何从 C# 应用程序中使用 Microsoft Access 数据库。 教程
本教程说明如何从 C# 中使用 Microsoft Access 数据库。它显示如何创建数据集并从数据库向该数据集添加表。本示例程序中使用的 BugTypes.mdb 数据库是 Microsoft Access 2000 .MDB 文件。 示例
本程序访问 BugTypes.mdb 数据库,创建一个数据集并向其中添加表,然后显示表、列和行的数目。它还显示每行的标题。 // OleDbSample.cs
using System;
using System.Data;
using System.Data.OleDb;
using System.Xml.Serialization; public class MainClass {
    public static void Main ()
    {
            // Set Access connection and select strings.
            // The path to BugTypes.MDB must be changed if you build
            // the sample from the command line:
#i......

阅读全文(1492) | 评论:0