C# 教程读书笔记

转载 2004年08月05日 10:19:00
================================================================================

?C# 教程读书笔记
?作者:plzw
?日期:2004-3-2 - 2004-3-15
================================================================================

目录
================================================================================
(一) C# 及 .Net Platform 概述
(二) C# Language
(三) 结语
================================================================================

正文
================================================================================
(一) C# 及 .Net Platform 概述
================================================================================
1. .Net 是一种面向网络、支持各种用户终端的开发平台环境。“支持各种用户终端”,意味着以后我们的终端不一定是 PC 机,可以是 PDA 乃至手机或者更为先进的终端。

2. C# 是为 .Net 平台量身打造的开发语言,在 .Net 平台下具有最高的效率。

3. 在面向对象方面,C# 抛弃了 C++ 语言的指针,但是在一些情况下,你也可以写一些非安全的代码,在这种情况下你仍然可以使用指针,C# 提供了替代指针的东西—— delegates,并且C# 和 Delphi 一样都是单一继承,一个类只有唯一的一个基类,它象 Delphi 一样使用接口来代替多重继承。

4. 在 Web 开发方面,C# 和 Web 更好的整合,XML 数据可以直接映射为 C# 的结构,这使得 Web 开发更加有效,快捷。

5. C# 使用 .Net Platform 提供的 GC 来负责资源的释放,在 C# 中使用了和 Delphi 一样的异常处理概念。

6. .Net Platform 的跨语言特性是由其 VOS(virtual OS) 提供的,VOS 既支持过程性语言也支持面向对象语言,同时提供了一个类型丰富的系统来容纳它所支持的各种语言的特性。

7. 当你使用一种编程语言的时候,由相应的 Compiler 编译成 IL 以及 Meta Data,当运行程序时再由 JIT Compiler 编译成本地代码,然后执行。

8. 书中说 Compiler 将 Source Code 编译成 IL 而不是直接编译成本地代码的目的是在于效率:在大型的应用中几乎只会用到其中的一部分功能,如此边执行边编译的效率要比直接编译来的高。这个解释似乎不太合理。

9. 一个简单 C# Console 代码的剖析:
// 引用命名空间,类似于 Delphi 中的 uses ,如果不引用命名空间,那么第 10-12行代

// 码就必须更改为:

// 10 ?System.Console.WriteLine("Please Enter Your Name:/n");

// 11 ?s = System.Console.ReadLine();
// 12 ?System.Console.WriteLine("Hello " + s + "/n");

1 ?using System;

// 声明命名空间 Hello

2 ?namespace Hello

3 ?{
// 声明一个类 Hello

4 ? ?class Hello
5 ? ?{
6 ? ? ?[STAThread]
// Main 方法是程序的入口

7 ? ? ?static void Main(string[] args)
8 ? ? ?{
9 ? ? ? ?string s;
10 ? ? ? ?Console.WriteLine("Please Enter Your Name:/n");
11 ? ? ? ?s = Console.ReadLine();
12 ? ? ? ?Console.WriteLine("Hello " + s + "/n");
// 该句代码也可以象下面这样写,类似使用了 Delphi 中的 Format 函数:

// 12 ? ? ? ?Console.WriteLine("Hello {0} /n", s);

13 ? ? ?}
14 ? ?}
15 ?}

10. 如果没有安装 VS.Net IDE,我们应使用 csc 来编译和执行程序,csc 支持编译选项,具体内容参阅 C# Online help。

11. C# 中单行注释用 //,多行注释用 /* ... */ 。
================================================================================
(二) C# Language
================================================================================
1. 数据类型:
?(1) 简单类型
? a.整型(sbyte, byte, short, ushort int, uint, long, ulong)
? ?各整型的取值范围见 C# Online help.
? b.布尔
? ?在 C/C++ 中,一切非零的整型值都视为 true,而在 C# 不存在这样的转换。
? c.字符
? ?
? d.实型(float, double)
? ?C# 提供了一种高精度128位的十进制类型,类似于 Delphi 中的 Currency,以下是一个声明范例:
? decimal value = 1.0m;
? 以下标 m 表示这是一个十进制类型,否则在赋值前 Compiler 会被自动视为 double 类型。

?(2)结构体
? C# 中有类似于 Delphi record 的结构体
? struct PhoneBook{
? ?public string name;
?public string Phone;
?public struct address{ ?// 可以把结构体类型作为另一个结构体的成员

? ?public string city;
? ?public string street;
? ?public uint no;
?}
? }
? PhoneBook pb;

?
?(3)枚举类型
? 和 Delphi 一样,C# 支持枚举类型
? enum WeekDay
?Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
? };
? WeekDay day;
? 枚举类型通常第一个元素对应0,接下来的递增1,但是也可以自定义第一个元素对应的 int 数值:
? enum WeekDay
?Sunday = 1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
? }; ?

?(4). 引用类型
? a. 类
? ?基于 OO 的多态性基类 System.Object 可以被赋任何值。
? b. 委托
? ?这个就是 C# 中用来替代指针的东西了!如果要使用这个东东,还必须声明这段程序是 unsafe 的。声明一个委托要指明委托指向原型的类型。
? ?delegate int MyDelegate();
? ?下面给出一个使用委托的例子:
? ?using System;

? ?delegate int MyDelegate();

? ?public class MyClass
? ?{
? ?public int InstanceMethod()
?{
? ?Console.WriteLine("Call the instance Method.");
? ?return 0;
?}
?
?static public int StaticMethod()
?{
? ?Console.WriteLine("Call the static instance Method.");
? ?return 0;
?}
? ?}
?
? ?public class Test
? ?{
?static public void Main()
?{
? ?MyClass obj = new MyClass();
? ?// 将委托指向非静态方法

? ?MyDelegate d = new MyDelegate(obj.InstanceMethod);
? ?// 调用非静态方法

? ?d();
? ?// 将委托指向静态方法

? ?d = new MyDelegate(MyClass.StaticMethod);
? ?// 调用静态方法

? ?d();
?}
? ?}

? c. 数组
? ?先来看一个数组使用的例子:
? ?using System;

? ?class Test
? ?{
?static void Main()
?{
? ?int[] arr = new int[5];
? ?for (int i=0; i? ? ?arr[i] = i*i;
? ?for (int i=0; i? ? ?Console.WriteLine("arr[{0}]={1}", i, arr[i]);
?}
? ?}
? ?上面的例子很好理解,看看复杂一点的,多维数组的声明:
? ?class Test
???{
?static void Main()
?{
? ?string[] a1; ? ?// 一维字符串数组

? ?string[,] a2; ? ?// 二维字符串数组

? ?string[,,] a3; ? ?// 三维字符串数组

? ?string [][] j1; ? ?// 可变数组

? ?string [][][][][] j2; ?// 多维可变数组

}
? ?}
? ?声明数组和声明其他简单类型的变量一样可以赋初值:
? ?using System;

? ?class Test
? ?{
?static void Main()
?{
? ?int[] a1 = new int[] {1,2,3};
? ?int[,] a2 = new int[,] {{1,2,3},{4,5,6}};
? ?int[,,] a3 = new int[10,20,30];
? ?int[][] j1 = new int[3][];
? ?j1[0] = new int[]{1,2,3};
? ?j1[1] = new int[]{1,2,3,4,5,6};
? ?j1[2] = new int[]{1,2,3,4,5,6,7,8};
?}
? ?}
? ?在数组初始化的时候一定要指明数组的类型,下面的写法是错误的:
? ?using System;
? ?class Test
? ?{
?static void Foo(int[] arg)
?{
?}
?static void Main()
?{
? ?Foo({1,2,3}); ? ?// 错误

???Foo(new int[]{1,2,3}); ?// 正确

?}
? ?}

2. boxing 是指将一个值类型隐式地转换成一个 object 类型,unboxing 是指将一个 object 类型显式地转换成一个值类型。

3. C# 中变量命名是允许以@开头的,但是这和其他语言的一些用法冲突,因此并不推荐这样命名。

4. 在 C# 中有以下七种变量类型:
?(1) 静态变量(static variables)
?(2) 非静态变量(instance variables)
?静态变量和非静态变量的不同点在于,静态变量是属于类的,而非静态变量是属于类实例的。
?(3) 数组元素(array elements)
?数组元素传递参数时,应使用 params 关键字,并且只能是一维数组。下面给出一个例子:
?using System;

?public class Test
?{
?static void Foo(params int[] args)
?{
? ?Console.WriteLine("Array contains {0} elements", args.Length);
? ?foreach(int i in args)
? ? ?Console.WriteLine("{0}", i);
?}
?
?public static void Main()
?{
? ?int[] arr = new int[5];
? ?for (int i=0; i< 5; i++)
? ? ?arr[i] = i * 2;
? ?Foo(arr);
? ?// 等价于 Foo(new int[] {8, 6, 4, 2});

? ?Foo(8, 6, 4, 2);
? ?// 等价于 Foo(new int[] {});

? ?Foo();
?}
?}
?(4) 值参数(value parameters)
?将参数的值做一份拷贝,然后将拷贝传递给函数,函数中做的任何操作都是对拷贝进行的,不改变原来的值。
?(5) 引用参数(reference parameters)
?将参数的地址传递给函数,函数中做的任何操作都将改变原来的值。类似于 Delphi 中使用 var 关键字传递的参数。下面给出一个例子:
?using System;

?public class Test
?{
?static void Foo(ref int a, ref int b)
?{
? ?a = 0;
? ?b = 1;
?}
?
?public static void Main()
?{
? ?int x = 10, y = 10;
? ?Foo(ref x, ref y);
? ?Console.WriteLine("x={0}/ty={1}", x, y);
?}
?}
?(6) 输出参数(output parameters)
?输出参数和引用参数不同的地方在于输出参数不需要对参数初始化。下面给出和上面类似的例子:
?using System;

?public class Test
?{
?static void Foo(out int a, out int b)
?{
? ?a = 0;
? ?b = 1;
?}
?
?public static void Main()
?{
? ?int x, y;
? ?Foo(out x, out y);
? ?Console.WriteLine("x={0}/ty={1}", x, y);
?}
?}
?(7) 局部变量(local variables)
?请看下面的例子:
?class A
?{
?public static int x; ? ? ? ? ?// 静态变量

?int y; ? ? ? ? ? ? ?// 非静态变量

?// v: 数组元素 a: 值参数 b: 引用参数 c: 输出参数

?void Foo(int[] v, int a, ref int b, out int c) ? ?
?{
? ?int i = 1; ? ? ? ? ?// 局部变量

? ?c = a + b++;
?}
?}

5. C# 中声明常量也是用 const 关键字,但是和 Delphi 有一些小小的差别,C# 中常量的声明格式如下:
?attributes constant-modifiers const type constant-declarators
?constant-modifiers 可以是 new public protected internal private 中的一个。

6. C# 支持三元操作符 ?,三元操作符比 if 条件句的效率更高。

7. 关于 i++ 和 ++i 一直是初学者最容易混淆的,只需要记住一点,除了 = 和 ?: 操作符是右结合的外,C# 的其他操作符都是左结合的。下面是一个最典型的例子帮助理解:
?using System;

?public class Test
?{
?static void Main()
?{
? ?int i;
? ?i = 0;
? ?Console.WriteLine("i++={0}", i++);
? ?Console.WriteLine("i={0}", i);
? ?i = 0;
? ?Console.WriteLine("++i={0}", ++i);
? ?Console.WriteLine("i={0}", i); ? ?
? ?Console.ReadLine();
?}
?}
?程序的输出为:
?i++=0
?i=1
?++i=1
?i=1

8. new 操作符用于创建类、数组、delegates 的实例。

9. typeof 操作符用于返回系统对象的类型。

10. checkedunchecked 操作符用于检查表达式是否溢出,如果使用 checked,当表达式溢出的话则在编译时期抛出异常,使用 unchecked,则不会抛出异常,将返回超过范围的低32位。下面是使用 checkedunchecked 的例子:
?using System;

?public class Test
?{
?static int x = 1000000;
?static int y = 1000000;
?public static void Main()
?{
? ?// 在编译时将抛出 OverFlowException 异常

? ?Console.WriteLine(checked(x*y));
? ?// 将输出 -727379968

? ?Console.WriteLine(unchecked(x*y));
?}
?}
?如果既不使用 checked,也不使用 unchecked 关键字,那么输出的结果取决于编译环境。

11. C# 中使用 switch 语句不允许遍历 case 标签,即每个 case 语句要用 break 或者 goto 跳转,否则会产生编译错误。如果确实需要遍历,可以使用 goto 语句来跳转到下个 case 标签。

12. C# 中的 switch 语句具有比 Delphi 中 case 语句更为强劲的功能,即允许字符串表达式,在 Delphi 中这个让人抓破脑袋的问题,在 C# 中可以轻松解决:
?using System;
?public class Test
?{
?public static void Main()
?{
? ?string s;
? ?s = Console.ReadLine();
? ?switch(s)
? ?{
? ? ?case "ok": ? ?
? ? ? ?System.Console.WriteLine(s);
? ? ? ?break;
? ? ?case "cancel":
? ? ? ?System.Console.WriteLine(s);
? ? ? ?break;
? ? ?default: ?
? ? ? ?System.Console.WriteLine("Your input is {0}", s);
? ? ? ?break;
? ?}
?}
?}

13. C# 提供了 foreach 语句,方便了对集合元素的遍历:
?using System;

?public class Test
?{
?public static void Main()
?{
? ?int[] arr = new int[5];
? ?for (int i=0; i<5; i++) ? ? ?// 数组初始化

? ? ?arr[i] = i;
? ?foreach(int j in arr) ? ? ?// 遍历

? ? ?Console.WriteLine(j);
?}
?}
?
14. #define #undefine 指令必须写在“实代码”之前用于预处理,有了预处理,我们就可以条件编译。下面是个预处理定义的例子:
?#define A
?#if A
?#define B
?#endif
?下面是条件编译的例子,里面用到了 C# 支持的四种条件编译语句:
?using System;

?public class Test
?{
?public static void Main()
?{
? ?#if DEBUG
? ?Console.WriteLine("DEBUG MESSAGE");
? ?#elif NORMAL
? ?Console.WriteLine("NORMAL MESSAGE");
? ?#else
? ?#endif
?}
?}
?另外通过结合条件编译和 #warning、#error 指令我们可以发出警告和错误提示。

15. C# 中提供了 try...catch...finally... 语句处理异常,而 throw 语句是用于抛出异常。下面给出一个简单的例子:
?using System;

?public class Test
?{
?public static void Main()
?{
? ?try
? ?{
? ? ?throw new Exception("My Exception");
? ?}
? ?catch(Exception e)
? ?{
? ? ?Console.WriteLine("Catch the exception:{0}", e.Message);
? ?}
? ?finally
? ?{
? ? ?Console.WriteLine("Perfect end.");
? ?}
?}
?}
?输出为:
?Catch the exception:My Exception
?Perfect end.

16. C# 声明类的格式如下:
?attributes class-modifiers class identifier class-base class-body
?class-modifiers 可以为以下的一种或者几种的组合:new public protected internal private abstract sealed,其中 public protectedprivate 与 Delphi 中类似,其他的含义如下:
?new: 仅允许在嵌套类声明时使用,表明类隐藏了由基类中继承来的、与基类同名的成员。
?new 关键字的使用类似于 Delphi 中的 reintroduce。
?internal: 只有其所在包才能访问
?abstract: 抽象类,不能创建该类的实例
?sealed: 密封类,不允许被继承,类似与 Java 中的 final

17. this 关键字和 Java 中一样,类似于 Delphi 中的 Self 关键字。而 base 则类似于 Java 中的 super 关键字。

18. C# 和 Java 一样,都是使用和类名称相同的一个方法作为构造函数;而析构函数则是在名称前面加上 ~ 符。

19. C# 也支持方法的重载,比 Delphi 更为简单的是,在 C# 中不需要使用任何关键字。

20. 在 C# 中支持操作符重载,允许重载的操作符为:+ - ! ~ ++ -- true false * / % & | ^ << >> == != > < >= <=,重载操作符必须在类中定义,通过类静态方法来实现。下面给出一个重载操作符 ++ 的例子:
?using System;

?public class Player
?{
?private int jing;
?private int qi;
?private int jingli;
?private int neili;
?public Player()
?{
? ?jing = 50;
? ?qi = 50;
? ?jingli = 50;
? ?neili = 50;
?}
?
?public static Player operator ++(Player p)
?{
? ?p.jing += 100;
? ?p.qi += 100;
? ?p.jingli += 100;
? ?p.neili += 100;
? ?return p;
?}
?public void hp()
?{
? ?string msg;
? ?msg = "jing: {0}/tjingli:{1}/nqi:{2}/t/tneili:{3}";
? ?Console.WriteLine(msg, jing, jingli, qi, neili);
?}
?
?}

?public class Test
?{
?public static void Main()
?{
? ?Player p = new Player();
? ?p.hp();
? ?p++;
? ?Console.WriteLine("Player p Updated!");
? ?p.hp();
?}
?}
?二元操作符的重载也和一元的类似,在此就不赘述了。

21. 在类的 field 前面加上 readonly 关键字即表示该 field 是只读的。类似于 Delphi 中的 read write 关键字,C# 中提供了 get set 关键字,下面是一个简单的例子:
?using System;

?public class File
?{
?private string FFileName;
?public string FileName
?{
? ?get
? ?{
? ? ?return FFileName;
? ?}
? ?set
? ?{
? ? ?if (FFileName != value)
? ? ? ?FFileName = value;
? ?}
?}
?}

?public class Test
?{
?public static void Main()
?{
? ?File F = new File();
? ?F.FileName = "FileName";
? ?Console.WriteLine(F.FileName);
?}
?}
?C# 中的索引值也使用 get set 关键字来实现:
?using System;

?public class MyClass
?{
?private int[] IntArr = new int[8];
?public int this[int Index]
?{
? ?get
? ?{
? ? ?return IntArr[Index];
? ?}
? ?set
? ?{
? ? ?if (IntArr[Index] != value)
? ? ? ?IntArr[Index] = value;
? ?}
?}
?}

?public class Test
?{
?public static void Main()
?{
? ?MyClass m = new MyClass();
? ?for (int i=0; i<8; i++)
? ?{
? ? ?m[i] = i;
? ? ?Console.WriteLine(m[i]);
? ?}
?}
?}

22. 为一个事件添加事件处理函数,在 C# 使用 += new EventHandler 这样的形式来实现:
例如:OkButton.Click += new EventHandler(OkButtonClick); 就是为 OkButon 的 click 事件添加 OkButtonClick 这个处理函数,如果要撤消事件处理函数则是使用 -= 来实现。

23. C# 的命名空间允许别名,下面是一个例子:
?using s = System;
?那么就可以用 s 来代替 System:
?s.Console.WriteLine("alias namespace?");

================================================================================
(三) 结语
================================================================================
C# 的语法及特性就学习到这里,关于 C# 中对文件操作以及对注册表的操作涉及到 .Net Framework,留到以后学习。

如何在RedHat8上装gcc2.96与gcc3.2并存

由于一些应用程序在使用过程中需要gcc2.96,而gcc3.2不能正常工作(比如Borland Enterprise Server 5.2.x),而你又不想装RedHat7.1的话,就需要在现有Red...
  • laughsky
  • laughsky
  • 2003-11-27 00:24:00
  • 984

C#教程

新建项目 打开VS (blend for Visual Studio 是专门做界面的,相当于PS; VS是写代码的) 新建项目——Visual C# ——控制台应用程序——项目名称——位置——确...
  • wds207207
  • wds207207
  • 2016-12-20 09:20:48
  • 1222

最全的前端资源教程

综合类 地址 前端知识体系 http://www.cnblogs.com/sb19871023/p/3894452.html 前端知识结构 https://github.c...
  • hcz297799265
  • hcz297799265
  • 2017-11-05 22:38:18
  • 527

搭建个人博客手把手教程

先看看我的初步成果:我的个人博客 大概可以分为以下几个步骤: 搭建环境准备(包括node.js和git环境,gitHub账户的配置) 安装Hexo 配置Hexo 怎样将Hexo与github...
  • qq_38646470
  • qq_38646470
  • 2018-03-12 19:01:58
  • 174

2018最新版hexo+Github搭建个人博客教程(2018-1-22 更新)

前言 现在是大三了,身边的甚多朋友技术都还不错,动不动就搭建自己的网站什么的。本着向大佬学习(zhuangbi)的心情,我也开始在阿里云上面买了一个云服务器(学生套餐9.9),使用phps...
  • qq_32454537
  • qq_32454537
  • 2018-03-08 12:57:02
  • 145

黄永成老师<em>教程</em>中的blog个人<em>博客</em>源码

黄永成老师thinkphp3.1.3版<em>教程</em>中的blog个人<em>博客</em>源码...所需: 3积分/<em>C</em>币 下载个数: 128 开通VIP 立即...qq_28649253 2015-09-<em>23</em> 11:59:07 一般般 后来重...
  • 2018年04月14日 00:00

C大学教程C++部分23章到25章

这个部分,我尽量每天都更新 chapter 23 Objected-oriented Programming :inheritanceBase Classes and Derived Classes...
  • RALPHFJY
  • RALPHFJY
  • 2017-03-01 14:43:45
  • 328

CMake 教程

CMake是一个跨平台的程序构建工具,比如起自己编写Makefile方便很多。 介绍:http://baike.baidu.com/view/1126160.htm 本文件不介绍CMake的基本语...
  • kaizi318
  • kaizi318
  • 2012-07-06 11:37:47
  • 22680

使用hexo+github搭建免费个人博客详细教程

前言 使用github pages服务搭建博客的好处有: 全是静态文件,访问速度快;免费方便,不用花一分钱就可以搭建一个自由的个人博客,不需要服务器不需要后台;可以随意绑定自己的域名,不仔...
  • qq_16149777
  • qq_16149777
  • 2017-09-23 12:40:52
  • 2076

hexo+github搭建个人博客(超详细教程)

首先呢,先说一下吧,作为一个程序猿来说,大多的大牛都是使用的是msdn/github这些来交流技术,但是我后来发现csdn上面好多的大牛都已经摒弃csdn,自己搭建个人博客进行发表文章记录点滴了。 虽...
  • AinUser
  • AinUser
  • 2017-08-26 23:48:37
  • 5582
收藏助手
不良信息举报
您举报文章:C# 教程读书笔记
举报原因:
原因补充:

(最多只允许输入30个字)