C# 教程读书笔记

目录
================================================================================
(一) 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.Length; i++)
arr[i] = i*i;
for (int i=0; i<arr.Length; 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. checked 和 unchecked 操作符用于检查表达式是否溢出,如果使用 checked,当表达式溢出的话则在编译时期抛出异常,使用 unchecked,则不会抛出异常,将返回超过范围的低32位。下面是使用 checked 和 unchecked 的例子:
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 protected 和 private 与 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,留到以后学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值