(1)方法C#中,一个类中可以定义多个方法,但相同签名的方法只能有一个。方法的签名包括: 方法的名称,形式参数的类型、个数、修饰符。如果方法是泛型方法,其签名还包括类型参数的个数。修饰符是指ref和out。参见:参数
(2)事件
事件相当于一个字段,这个字段是一个委托类型。但在类体的外面,只能在事件上执行+=或-=操作。也可以将事件定义成这样:
add和remove访问器类似属性里面的get和set。
(3)索引器
提供类似数组模式的成员访问。
(4)类
方法、属性、索引器都可以是virtual的,意味着在子类中可以得到重写。
(5)静态类
像这样:
静态类只能这样用,typeof(Months)或者Months.IsLeapYear(200),不能被继承、实例化或者作为泛型类型参数。
(6)结构
结构和类相似,可以实现接口,却不能继承类或被继承。
举例:
问Main方法中共有几个对象?一个points数组,和100个Point,共101个。
如果是这样呢?只有一个对象,就是points数组。
(7)接口
接口可以包含的成员是:
方法,属性,索引器,事件。接口中的成员默认都是public的,不能有任何访问修饰符。
实现时,必须实现为public:
如果要实现为private的,那就"显示实现":
这样用:
实现时默认为private,不能有任何修饰符。
(8)代理
代理相当于C语言中的函数指针。c#中的代理值面向对象的(和class一样是一种类型),同时是类型安全的。
一个代理可以封装一个或多个方法,这些方法被成为“调用实体”。执行这个代理时,这些方法都将被调用。
方法可以是实例方法,也可以是静态方法。包含方法的类可以是任意的(甚至可以是匿名方法,即没有类的存在!),只要方法的定义和代理的定义相一致。
定义和使用:
像方法一样使用代理。代理的返回值是,最后一个方法的返回值:
上述代码使用了NUnit。简单介绍:[TestFixture]是一个c#中的特性(Attribute),这样Nunit就认为DelegateTest类是包含测试方法的类。 同样,[Test]标记了方法TestDelegate,意味着这个方法是一个测试方法。 测试方法返回值是void,没有参数,必须是public的,保证Nunit能调用到。Assert.That(dele(), Is.EqualTo(get2()));断言dele()的结果是get2()。断言失败则测试不通过。 (9)枚举 例子: 1 enum Color 2 { 3 Red, 4 Blue, 5 Green 6 } 7 class Shape 8 { 9 public void Fill(Color color) { 10 switch(color) { 11 case Color.Red: 12 … 13 break; 14 case Color.Blue: 15 … 16 break; 17 case Color.Green: 18 … 19 break; 20 default: 21 break; 22 } 23 } 24 } 枚举相当于符号常量的集合,这些符号常量是整型的,默认实现是int: 1 enum Fruit1 2 { 3 Apple, Orange 4 } 5 enum Fruit2:byte 6 { 7 Apple,Orange 8 } 9 10 [TestFixture] 11 public class EnumTest 12 { 13 [Test] 14 public void TestEnum() 15 { 16 Fruit1 f = Fruit1.Apple; 17 Assert.That(Enum.GetUnderlyingType(typeof(Fruit1)),Is.EqualTo(typeof(int))); 18 Assert.That(Enum.GetUnderlyingType(typeof(Fruit2)), Is.EqualTo(typeof(byte))); 19 Assert.That(Enum.GetValues(typeof(Fruit1)), Is.EqualTo(new Fruit1[] { Fruit1.Apple,Fruit1.Orange }).AsCollection); 20 21 } 22 } 注意Fruit2用byte作为枚举常量的类型。
(2)事件
事件相当于一个字段,这个字段是一个委托类型。但在类体的外面,只能在事件上执行+=或-=操作。也可以将事件定义成这样:
1 public class Button
2 {
3 private EventHandler handler;
4 public event EventHandler Click
5 {
6 add { handler += value; }
7 remove { handler -= value; }
8 }
9 }
2 {
3 private EventHandler handler;
4 public event EventHandler Click
5 {
6 add { handler += value; }
7 remove { handler -= value; }
8 }
9 }
add和remove访问器类似属性里面的get和set。
(3)索引器
提供类似数组模式的成员访问。
1 public class Stack
2 {
3 private Node GetNode(int index) {
4 Node temp = first;
5 while (true) {
6 if (temp == null || index < 0)
7 throw new Exception("Index out of range.");
8 if (index == 0)
9 return temp;
10 temp = temp.Next;
11 index--;
12 }
13 }
14 public object this[int index] {
15 get {
16 return GetNode(index).Value;
17 }
18 set {
19 GetNode(index).Value = value;
20 }
21 }
22 …
23 }
24 class Test
25 {
26 static void Main() {
27 Stack s = new Stack();
28 s.Push(1);
29 s.Push(2);
30 s.Push(3);
31 s[0] = 33; // Changes the top item from 3 to 33
32 s[1] = 22; // Changes the middle item from 2 to 22
33 s[2] = 11; // Changes the bottom item from 1 to 11
34 }
35 }
2 {
3 private Node GetNode(int index) {
4 Node temp = first;
5 while (true) {
6 if (temp == null || index < 0)
7 throw new Exception("Index out of range.");
8 if (index == 0)
9 return temp;
10 temp = temp.Next;
11 index--;
12 }
13 }
14 public object this[int index] {
15 get {
16 return GetNode(index).Value;
17 }
18 set {
19 GetNode(index).Value = value;
20 }
21 }
22 …
23 }
24 class Test
25 {
26 static void Main() {
27 Stack s = new Stack();
28 s.Push(1);
29 s.Push(2);
30 s.Push(3);
31 s[0] = 33; // Changes the top item from 3 to 33
32 s[1] = 22; // Changes the middle item from 2 to 22
33 s[2] = 11; // Changes the bottom item from 1 to 11
34 }
35 }
(4)类
方法、属性、索引器都可以是virtual的,意味着在子类中可以得到重写。
(5)静态类
像这样:
1 public static class Months
2 {
3 static Months() { … }
4 private static readonly string[] monthName = { … }
5 public static string GetMonthName(int mm) { … }
6 private static readonly int[,] daysInMonth = { … }
7 public static int GetDaysInMonth(bool isLeapYear, int mm) { … }
8 public static bool IsLeapYear(int yy) { … }
9 }
2 {
3 static Months() { … }
4 private static readonly string[] monthName = { … }
5 public static string GetMonthName(int mm) { … }
6 private static readonly int[,] daysInMonth = { … }
7 public static int GetDaysInMonth(bool isLeapYear, int mm) { … }
8 public static bool IsLeapYear(int yy) { … }
9 }
静态类只能这样用,typeof(Months)或者Months.IsLeapYear(200),不能被继承、实例化或者作为泛型类型参数。
(6)结构
结构和类相似,可以实现接口,却不能继承类或被继承。
举例:
1 class Point
2 {
3 public int x, y;
4 public Point(int x, int y) {
5 this.x = x;
6 this.y = y;
7 }
8 }
9 class Test
10 {
11 static void Main() {
12 Point[] points = new Point[100];
13 for (int i = 0; i < 100; i++)
14 points[i] = new Point(i, i*i);
15 }
16 }
2 {
3 public int x, y;
4 public Point(int x, int y) {
5 this.x = x;
6 this.y = y;
7 }
8 }
9 class Test
10 {
11 static void Main() {
12 Point[] points = new Point[100];
13 for (int i = 0; i < 100; i++)
14 points[i] = new Point(i, i*i);
15 }
16 }
问Main方法中共有几个对象?一个points数组,和100个Point,共101个。
1 struct Point
2 {
3 public int x, y;
4 public Point(int x, int y) {
5 this.x = x;
6 this.y = y;
7 }
8 }
9 class Test
10 {
11 static void Main() {
12 Point[] points = new Point[100];
13 for (int i = 0; i < 100; i++)
14 points[i] = new Point(i, i*i);
15 }
16 }
2 {
3 public int x, y;
4 public Point(int x, int y) {
5 this.x = x;
6 this.y = y;
7 }
8 }
9 class Test
10 {
11 static void Main() {
12 Point[] points = new Point[100];
13 for (int i = 0; i < 100; i++)
14 points[i] = new Point(i, i*i);
15 }
16 }
如果是这样呢?只有一个对象,就是points数组。
(7)接口
接口可以包含的成员是:
方法,属性,索引器,事件。接口中的成员默认都是public的,不能有任何访问修饰符。
1 interface IExample
2 {
3 string this[int index] { get; set; }
4 event EventHandler E;
5 void F(int value);
6 string P { get; set; }
7 }
8 public delegate void EventHandler(object sender, EventArgs e);
2 {
3 string this[int index] { get; set; }
4 event EventHandler E;
5 void F(int value);
6 string P { get; set; }
7 }
8 public delegate void EventHandler(object sender, EventArgs e);
实现时,必须实现为public:
1 interface IControl
2 {
3 void Paint();
4 }
5 interface IDataBound
6 {
7 void Bind(Binder b);
8 }
9 public class EditBox: Control, IControl, IDataBound
10 {
11 public void Paint() {…}
12 public void Bind(Binder b) {…}
13 }
2 {
3 void Paint();
4 }
5 interface IDataBound
6 {
7 void Bind(Binder b);
8 }
9 public class EditBox: Control, IControl, IDataBound
10 {
11 public void Paint() {…}
12 public void Bind(Binder b) {…}
13 }
如果要实现为private的,那就"显示实现":
1 public class EditBox: IControl, IDataBound
2 {
3 void IControl.Paint() {…}
4 void IDataBound.Bind(Binder b) {…}
5 }
2 {
3 void IControl.Paint() {…}
4 void IDataBound.Bind(Binder b) {…}
5 }
这样用:
1 class Test
2 {
3 static void Main() {
4 EditBox editbox = new EditBox();
5 editbox.Paint(); // error: no such method
6 IControl control = editbox;
7 control.Paint(); // calls EditBox’s Paint implementation
8 }
9 }
2 {
3 static void Main() {
4 EditBox editbox = new EditBox();
5 editbox.Paint(); // error: no such method
6 IControl control = editbox;
7 control.Paint(); // calls EditBox’s Paint implementation
8 }
9 }
实现时默认为private,不能有任何修饰符。
(8)代理
代理相当于C语言中的函数指针。c#中的代理值面向对象的(和class一样是一种类型),同时是类型安全的。
一个代理可以封装一个或多个方法,这些方法被成为“调用实体”。执行这个代理时,这些方法都将被调用。
方法可以是实例方法,也可以是静态方法。包含方法的类可以是任意的(甚至可以是匿名方法,即没有类的存在!),只要方法的定义和代理的定义相一致。
定义和使用:
1 delegate void SimpleDelegate();
2 class Test
3 {
4 static void F() {
5 System.Console.WriteLine("Test.F");
6 }
7 static void Main() {
8 SimpleDelegate d = new SimpleDelegate(F);
9 d();
10 }
11 }
2 class Test
3 {
4 static void F() {
5 System.Console.WriteLine("Test.F");
6 }
7 static void Main() {
8 SimpleDelegate d = new SimpleDelegate(F);
9 d();
10 }
11 }
像方法一样使用代理。代理的返回值是,最后一个方法的返回值:
1 delegate string GetAString();
2 [TestFixture]
3 public class DelegateTest
4 {
5 public string get1()
6 {
7 return "get1";
8 }
9 public string get2()
10 {
11 return "get2";
12 }
13 [Test]
14 public void TestDelegate()
15 {
16 GetAString dele = new GetAString(get1);
17 dele += get2;
18 Assert.That(dele(), Is.EqualTo(get2()));
19 }
20 }
2 [TestFixture]
3 public class DelegateTest
4 {
5 public string get1()
6 {
7 return "get1";
8 }
9 public string get2()
10 {
11 return "get2";
12 }
13 [Test]
14 public void TestDelegate()
15 {
16 GetAString dele = new GetAString(get1);
17 dele += get2;
18 Assert.That(dele(), Is.EqualTo(get2()));
19 }
20 }
上述代码使用了NUnit。简单介绍:[TestFixture]是一个c#中的特性(Attribute),这样Nunit就认为DelegateTest类是包含测试方法的类。 同样,[Test]标记了方法TestDelegate,意味着这个方法是一个测试方法。 测试方法返回值是void,没有参数,必须是public的,保证Nunit能调用到。Assert.That(dele(), Is.EqualTo(get2()));断言dele()的结果是get2()。断言失败则测试不通过。 (9)枚举 例子: 1 enum Color 2 { 3 Red, 4 Blue, 5 Green 6 } 7 class Shape 8 { 9 public void Fill(Color color) { 10 switch(color) { 11 case Color.Red: 12 … 13 break; 14 case Color.Blue: 15 … 16 break; 17 case Color.Green: 18 … 19 break; 20 default: 21 break; 22 } 23 } 24 } 枚举相当于符号常量的集合,这些符号常量是整型的,默认实现是int: 1 enum Fruit1 2 { 3 Apple, Orange 4 } 5 enum Fruit2:byte 6 { 7 Apple,Orange 8 } 9 10 [TestFixture] 11 public class EnumTest 12 { 13 [Test] 14 public void TestEnum() 15 { 16 Fruit1 f = Fruit1.Apple; 17 Assert.That(Enum.GetUnderlyingType(typeof(Fruit1)),Is.EqualTo(typeof(int))); 18 Assert.That(Enum.GetUnderlyingType(typeof(Fruit2)), Is.EqualTo(typeof(byte))); 19 Assert.That(Enum.GetValues(typeof(Fruit1)), Is.EqualTo(new Fruit1[] { Fruit1.Apple,Fruit1.Orange }).AsCollection); 20 21 } 22 } 注意Fruit2用byte作为枚举常量的类型。