01.C#核心语法

1.特殊的数据成员

(1)常量const

定义方式:const int g = 10;

注意:常量的值必须在声明时初始化,常量的值不可变化,常量本身就是静态的不能使用static修饰。

(2)只读字段readonly

定义方式:private readonly int t;

注意:只读字段必须在声明时或类构造方法中初始化,只读字段的值不可变化,只读字段不一定是静态的可以使用static修饰。

2.数组(array)

(1)一维数组

定义方式:

int[] array=new int[num];

int[] array = { 1, 2, 3, 4, 5, 6 };

int[] array = new int[] { 1, 2, 3, 4, 5, 6 };

(2)多维数组

定义方式:

int[,] array=new int[low,row];

int[,] array={{1,2},{5,6}};(一维的维度要一致)

int[,] array = new int[2,2]{{1,2},{5,6}};

(3)不规则数组(数组的数组)

int[][] array=new int[3][];

array[0]
= new int[] { 1, 2, 3, 4 };

array[1]
= new int[] { 1, 2, 3};

array[2]
= new int[] { 1, 2};

int[][,] array=new int[3][,];

(4)数组遍历

遍历规则数组:

  1. for (int i = 0; i < array.GetLength(0); i++)
  2. {
  3. for (int j = 0; j < array.GetLength(1); j++)
  4. {
  5. Console.Write(array[i, j] + " ");
  6. }
  7. Console.WriteLine();
  8. }

遍历不规则数组:

  1. for (int i = 0; i < array.Length; i++)
  2. {
  3. for (int j = 0; j < array[i].Length; j++)
  4. {
  5. Console.Write(array[i][j] + " ");
  6. }
  7. Console.WriteLine();
  8. }

3.命名空间(namespace)

C#命名空间与Java的包一样,不同的程序文件里的类可以在同一命名空间里。命名空间可以嵌套。

4.方法的参数传递

(1)值传递

代码形式:方法名称 (参数类型 参数名称)

说明:此方式并无特别之处。

(2)引用参数(ref)

代码形式:方法名称 (ref 参数类型 参数名称)

说明:传递参数的引用可以改变原参数(实参),但是需要初始化实参。下面代码输出1。

  1. class Program
  2. {
  3. static void add(ref int i)
  4. {
  5. i++;
  6. }
  7. static void Main(string[] args)
  8. {
  9. int i = 0;//必须先初始化
  10. add(ref i);//调用时必须加ref
  11. Console.WriteLine(i);
  12. }
  13. }

(3)输出参数(out)

代码形式:方法名称 (out 参数类型 参数名称)

说明:传递参数的引用可以改变原参数(实参),但是在使用前需要初始化参数。下面代码输出100。

  1. class Program
  2. {
  3. static void add(out int i)
  4. {
  5. i = 0;//必须在使用前初始化
  6. i = 100;
  7. }
  8. static void Main(string[] args)
  9. {
  10. int i;
  11. add(out i);//调用时必须加out
  12. Console.WriteLine(i);
  13. }
  14. }

(4)传递可变数量的参数(params)

代码形式:方法名称 (params参数类型 参数名称)

说明:传递的参数数量不定,可以变化。下面的程序输出1 2 3。

  1. class Program
  2. {
  3. static void Print(params int[] array)
  4. {
  5. foreach (int i in array)
  6. {
  7. Console.Write(i + " ");
  8. }
  9. }
  10. static void Main(string[] args)
  11. {
  12. Print(1, 2);
  13. Print(3);
  14. }
  15. }

5.构造器(constructor)

(1)创建对象的过程—无参构造器

  1. class A
  2. {
  3. public A(int i) { }
  4. }
  5. class B : A
  6. {
  7. }
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. new B();//无法创建对象
  13. }
  14. }

以上的程序无法创建B类对象,因为创建B类对象调用B类的默认构造器时会默认的调用其基类A的无参构造器,而A类却没有无参构造器,所以不能创建B类对象。

(2)使用base调用基类构造器

  1. class A
  2. {
  3. public A(int i) { }
  4. }
  5. class B : A
  6. {
  7. public B() : base(5) { }//调用A类的有参构造
  8. }
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. new B();//可以创建对象
  14. }
  15. }

(3)静态构造器(Java中的静态初始化器)

静态构造器最多执行一次,执行在静态成员初始化完毕之后。下面程序输出20。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Console.WriteLine(A.i);
  6. }
  7. }
  8. class A
  9. {
  10. public static int i = 10;
  11. static A()
  12. {
  13. i = 20;
  14. }
  15. }

6.析构(Destructor)

(1)析构函数(Finalize操作)

下面程序运行结果:构造A构造A析构A析构A。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. new A();
  6. new A();
  7. }
  8. }
  9. class A
  10. {
  11. public A()
  12. {
  13. Console.Write("构造A");
  14. }
  15. ~A()//析构
  16. {
  17. Console.Write("析构A");
  18. }
  19. }

(2)在一般情况下不要实现析构函数,这会影响垃圾回收的性能。

(3)显示调用垃圾回收:GC.Collect()会建议程序调用垃圾回收,微软强烈建议不要这样做!

(4)释放模式,IDisposable接口

  1. class A : IDisposable
  2. {
  3. private bool disposed = false;//标志是否已释放资源
  4. protected virtual void Dispose(bool disposing)
  5. {
  6. if (!this.disposed)
  7. {
  8. if (disposing)
  9. {
  10. Console.WriteLine("调用所引用的类的Dispose()方法!");
  11. }
  12. Console.WriteLine("调用类本身的非托管资源!");
  13. disposed = true;
  14. }
  15. }
  16. public void Dispose()
  17. {
  18. Dispose(true);//调用手动释放资源
  19. GC.SuppressFinalize(this);//阻止调用终结器
  20. }
  21. ~A()
  22. {
  23. Dispose(false);
  24. }
  25. }

对于下面主方法,执行结果:调用类本身的非托管资源!

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. A a = new A();
  6. }
  7. }

对于下面主方法,执行结果:

调用所引用的类的Dispose()方法!

调用类本身的非托管资源!

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. A a = new A();
  6. a.Dispose();
  7. a.Dispose();
  8. }
  9. }

(5)对于继承了IDisposable接口的类,使用using简化try{}finally{}

对于下面的两个主方法,执行结果都是:

使用a对象

调用所引用的类的Dispose()方法!

调用类本身的非托管资源!

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. A a = new A();
  6. try
  7. { Console.WriteLine("使用a对象"); }
  8. finally
  9. { a.Dispose(); }
  10. }
  11. }
  12. class Program
  13. {
  14. static void Main(string[] args)
  15. {
  16. A a = new A();
  17. using (a)//使用using
  18. {
  19. Console.WriteLine("使用a对象");
  20. }
  21. }
  22. }

7.访问控制修饰符

(1)修饰符的访问范围(空白表示不能访问)

?


?访问控制修饰符


类内部


子类


程序集内


程序集外


default


可以访问


public


可以访问


可以访问


可以访问


可以访问


private


可以访问


internal


可以访问


可以访问


可以访问


protected


可以访问


可以访问


protected internal


可以访问


可以访问


可以访问


子类可以访问

(2)总结

    在C#1.0中,不声明任何修饰符,默认是私有的方法,也就是说default与private一样。当父类和子类在同一程序集时,子类可以访问父类的internal成员,当父类和子类不在同一程序集时,子类不可以访问父类的internal成员,但可以访问父类的protected interal成员。

8.类型转换

(1)使用checked与unchecked检测抓换的异常(如:溢出)

下面程序会出现溢出异常,而中断执行。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. long a = 1000000000000;
  6. int b;
  7. b = checked((int)a);//使用checked检测是否溢出
  8. }
  9. }

下面程序会忽略溢出异常。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. long a = 1000000000000;
  6. int b;
  7. b = unchecked((int)a);//使用unchecked忽略溢出异常,默认也是忽略溢出异常
  8. }
  9. }

(2)使用is判断类型

下面程序的执行结果:True False True True

  1. class A
  2. { }
  3. class B : A
  4. { }
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. A a = new A();
  10. B b = new B();
  11. Console.WriteLine(a is A);
  12. Console.WriteLine(a is B);
  13. Console.WriteLine(b is A);
  14. Console.WriteLine(b is B);
  15. }
  16. }

(3)使用as操作符(使用as比is效率高)

  1. class A
  2. { }
  3. class B : A
  4. { }
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. A a = new A();
  10. B b = a as B;//转换失败返回null
  11. if (a != null)
  12. {
  13. Console.WriteLine("转换成功");
  14. }
  15. }
  16. }

9.属性(Property)

(1)使用属性访问私有成员

  1. class A
  2. {
  3. private string m_name;
  4. public string Name
  5. {
  6. get
  7. { return m_name; }
  8. set
  9. {
  10. if (value != null)//赋值前的处理
  11. m_name = value;
  12. }
  13. }
  14. }
  15. class Program
  16. {
  17. static void Main(string[] args)
  18. {
  19. A a = new A();
  20. a.Name = "lizhiwei";
  21. Console.WriteLine(a.Name);
  22. }
  23. }

(2)访问静态成员的属性

  1. class A
  2. {
  3. private static int m_num = 0;
  4. public A()
  5. {
  6. m_num++;
  7. }
  8. public static int Num
  9. {
  10. get
  11. { return m_num; }
  12. }
  13. }
  14. class Program
  15. {
  16. static void Main(string[] args)
  17. {
  18. new A();
  19. Console.WriteLine(A.Num);
  20. new A();
  21. Console.WriteLine(A.Num);
  22. }
  23. }

10.索引器(indexer)

(1)使用索引器

下面程序运行结果:1 2

  1. class A
  2. {
  3. private int[] array = new int[20];
  4. public int this[int index]//索引器
  5. {
  6. get
  7. { return array[index]; }
  8. set
  9. { array[index] = value; }
  10. }
  11. }
  12. class Program
  13. {
  14. static void Main(string[] args)
  15. {
  16. A a = new A();
  17. a[0] = 1;//访问索引器set
  18. a[19] = 2;//访问索引器set
  19. Console.WriteLine(a[0] + " " + a[19]);//访问索引器get
  20. }
  21. }

(2)索引器的重载

下面的程序运行结果:lizhiwei li

  1. class A
  2. {
  3. private Hashtable m_map = new Hashtable();
  4. public string this[string key]//索引器
  5. {
  6. get
  7. { return m_map[key].ToString(); }
  8. set
  9. { m_map[key] = value; }
  10. }
  11. public string this[int key]//重载索引器
  12. {
  13. get
  14. { return m_map[key].ToString(); }
  15. set
  16. { m_map[key] = value; }
  17. }
  18. }
  19. class Program
  20. {
  21. static void Main(string[] args)
  22. {
  23. A a = new A();
  24. a["001"] = "lizhiwei";
  25. a[2] = "li";
  26. Console.WriteLine(a["001"] + " " + a[2]);
  27. }
  28. }

(3)多参数的索引器

下面程序运行结果:20 10

  1. class A
  2. {
  3. private string m_name;
  4. private int m_age;
  5. private string m_sex;
  6. public string Name
  7. {
  8. get
  9. { return m_name; }
  10. set
  11. { m_name = value; }
  12. }
  13. public int Age
  14. {
  15. get
  16. { return m_age; }
  17. set
  18. { m_age = value; }
  19. }
  20. public string Sex
  21. {
  22. get
  23. { return m_sex; }
  24. set
  25. { m_sex = value; }
  26. }
  27. }
  28. class B
  29. {
  30. private ArrayList m_list = new ArrayList();
  31. public int this[string name, string sex]
  32. {
  33. get
  34. {
  35. foreach (A a in m_list)
  36. {
  37. if (a.Name.Equals(name) && a.Sex.Equals(sex))
  38. {
  39. return a.Age;
  40. }
  41. }
  42. return -1;
  43. }
  44. set
  45. {
  46. A a = new A();
  47. a.Name = name;
  48. a.Sex = sex;
  49. a.Age = value;//value的类型与返回值类型一致(这里是int)
  50. m_list.Add(a);
  51. }
  52. }
  53. }
  54. class Program
  55. {
  56. static void Main(string[] args)
  57. {
  58. B b = new B();
  59. b["李志伟", "男"] = 20;
  60. b["张三", "男"] = 10;
  61. Console.Write(b["李志伟", "男"] + " " + b["张三", "男"]);
  62. }
  63. }

(4)注意:索引器不能是静态(static)的!

11.委托(delegate)

(1)委托的使用(类似指向函数的指针)

下面程序运行结果:李志伟

  1. delegate void PrintDelegate(string s);//申明委托
  2. class A
  3. {
  4. public void Print(string s)//与委托的返回值、参数相同的函数
  5. {
  6. Console.WriteLine(s);
  7. }
  8. }
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. A a = new A();
  14. PrintDelegate s = new PrintDelegate(a.Print);//新建委托链
  15. s("李志伟");//执行委托连
  16. }
  17. }

(2)委托链的使用

下面程序的运行结果:

a1李志伟 a2李志伟 a2李志伟

a1李志伟 a2李志伟

  1. delegate void PrintDelegate(string s);//申明委托
  2. class A
  3. {
  4. private string name;
  5. public A(string name)
  6. {
  7. this.name = name;
  8. }
  9. public void Print(string s)//与委托的返回值、参数相同的函数
  10. {
  11. Console.Write(name + s + " ");
  12. }
  13. }
  14. class Program
  15. {
  16. static void Main(string[] args)
  17. {
  18. A a1 = new A("a1");
  19. A a2 = new A("a2");
  20. PrintDelegate s = new PrintDelegate(a1.Print);//新建委托链
  21. s += new PrintDelegate(a2.Print);//增加委托链
  22. s += new PrintDelegate(a2.Print);//增加委托链
  23. s("李志伟");//执行委托链
  24. Console.WriteLine();
  25. s -= new PrintDelegate(a2.Print);//减少委托链
  26. s("李志伟");//执行委托链
  27. }
  28. }

(3)直接使用委托调用匿名方法

  1. delegate void PrintDelegate(string s);//申明委托
  2. class Program
  3. {
  4. static void Main(string[] args)
  5. {
  6. PrintDelegate s = null;
  7. s += delegate(string temp) { Console.WriteLine(temp); };//委托指向匿名方法
  8. s("李志伟");//执行委托连
  9. }
  10. }

(4)使用Action<T>与Func<in T,out TResult>省略委托的定义

当委托没有返回值时使用Action<T>,有返回值时使用Func<in T,out TResult>。例如:

  1. class Program
  2. {
  3. private void Hello(string name)//无返回值
  4. {
  5. Console.WriteLine("你好," + name + "!");
  6. }
  7. private string GETAge(int age)//有返回值
  8. {
  9. Console.WriteLine("我的年龄:" + age + "!");
  10. return "我的年龄:" + age + "!";
  11. }
  12. static void Main(string[] args)
  13. {
  14. Program p = new Program();
  15. Action<string> action = p.Hello;
  16. //Action<string> hello = new Action<string>(p.Hello);
  17. action("李志伟");//执行委托
  18. Func<int, string> fun = p.GETAge;
  19. Console.WriteLine(fun(20));//执行委托
  20. }
  21. }

(5)Lambda表达式,方便的使用匿名方法

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. //标准的Lambda格式
  6. Func<int, int, string> sum = (int a, int b) => { return "和是:" + (a + b); };
  7. Console.WriteLine(sum(5, 6));//和是:11
  8. //简写格式
  9. Action<string> action = param => Console.WriteLine(param);//委托匿名方法
  10. action("调用委托");
  11. Func<int, Double> func = param => param * param;//有返回值的匿名方法
  12. Console.WriteLine(func(5));//25,调用委托返回25
  13. }
  14. }

12.事件(event)

(1)实现事件委托的原理

下面的程序运行的结果:

事件被触发,执行事件委托链!

执行触发事件执行的方法!

执行触发事件执行的方法!

  1. class A
  2. {
  3. public delegate void Publish();//事件方法的委托
  4. public event Publish OnPublish;//事件委托链
  5. public void OnEvent()//触发事件,执行事件委托链
  6. {
  7. if (OnPublish != null)//事件委托链不为null
  8. {
  9. Console.WriteLine("事件被触发,执行事件委托链!");
  10. OnPublish();//执行事件委托链
  11. }
  12. }
  13. public void Event()//触发事件执行的方法
  14. {
  15. Console.WriteLine("执行触发事件执行的方法!");
  16. }
  17. }
  18. class Program
  19. {
  20. static void Main(string[] args)
  21. {
  22. A a = new A();
  23. a.OnPublish += new A.Publish(a.Event);//订阅(注册)事件,本质是增加委托链
  24. a.OnPublish += new A.Publish(a.Event);//订阅(注册)事件,本质是增加委托链
  25. a.OnEvent();//触发事件,执行事件委托链
  26. }
  27. }

(2).NET Framework事件设计准则

申明delegate时,使用void类型当做返回值,EventName事件的事件委托时EventNameEventHandler,事件接受两个传入参数,一律命名sender与e。定义一个提供事件数据的类,对类EventNameEventArgs进行命名,从System.EventArgs派生该类,然后添加所有事件特定的成员。

  1. //包含事件数据的类,命名方式:EventNameEventArgs
  2. class AEventArgs : EventArgs
  3. {
  4. private readonly string name;//只读属性
  5. public AEventArgs(string name)
  6. {
  7. this.name = name;
  8. }
  9. public string Name
  10. {
  11. get
  12. { return name; }
  13. }
  14. }
  15. //引发事件的类
  16. class B
  17. {
  18. //事件方法的委托,命名方式EventNameEventHandler
  19. public delegate void PublishEventHandler(object sender, AEventArgs e);
  20. //事件委托链
  21. public event PublishEventHandler Publish;
  22. //引发执行事件委托链的方法,命名方式:OnEventName
  23. protected virtual void OnEvent(AEventArgs e)
  24. {
  25. PublishEventHandler handler = Publish;
  26. if (handler != null)
  27. {
  28. handler(this, e);
  29. }
  30. }
  31. //触发事件的方法
  32. public void TriggerEvent(string name)
  33. {
  34. Console.WriteLine("事件被触发!!!");
  35. //调用引发执行事件委托链的方法
  36. OnEvent(new AEventArgs(name));
  37. }
  38. //事件处理的方法
  39. public void HandlingEvents(object sender, AEventArgs e)
  40. {
  41. Console.WriteLine(e.Name + " 处理事件!!!");
  42. }
  43. }
  44. class Program
  45. {
  46. static void Main(string[] args)
  47. {
  48. B b = new B();
  49. //订阅(注册)事件,本质是增加委托链
  50. b.Publish += new B.PublishEventHandler(b.HandlingEvents);
  51. b.TriggerEvent("李志伟");
  52. }
  53. }

上面的程序使用了.NET Framework事件设计准则,运行结果:

事件被触发!!!

李志伟 处理事件!!!

13.虚方法(virtual)

(1)使用new隐藏基类方法

下面的程序运行结果:A.print  B.print

  1. class A
  2. {
  3. public void print()
  4. {
  5. Console.WriteLine("A.print");
  6. }
  7. }
  8. class B : A
  9. {
  10. public new void print()//使用new显示的隐藏基类相同方法
  11. {
  12. Console.WriteLine("B.print");
  13. }
  14. }
  15. class Program
  16. {
  17. static void Main(string[] args)
  18. {
  19. B b = new B();
  20. A a = b;
  21. a.print();//A.print
  22. b.print();//B.print
  23. }
  24. }

(2)使用virtual与override覆盖基类方法(实现了多态)

下面程序运行结果:B.print  B.print

  1. class A
  2. {
  3. public virtual void print()//使用virtual申明虚方法
  4. {
  5. Console.WriteLine("A.print");
  6. }
  7. }
  8. class B : A
  9. {
  10. public override void print()//使用override覆盖基类虚方法
  11. {
  12. Console.WriteLine("B.print");
  13. }
  14. }
  15. class Program
  16. {
  17. static void Main(string[] args)
  18. {
  19. B b = new B();
  20. A a = b;
  21. a.print();//B.print
  22. b.print();//B.print
  23. }
  24. }

14.抽象类(abstract)

(1)抽象类的使用

  1. abstract class A
  2. {
  3. protected string m_name;
  4. public abstract void print();//抽象方法
  5. public abstract string Name//抽象属性,也可使用抽象索引器
  6. {
  7. set;
  8. get;
  9. }
  10. }
  11. class B : A
  12. {
  13. public override void print()//必须使用override或new,否则报错
  14. {
  15. Console.WriteLine(base.m_name);
  16. }
  17. public override string Name//必须使用override或new,否则报错
  18. {
  19. set { base.m_name = value; }
  20. get { return base.m_name; }
  21. }
  22. }
  23. class Program
  24. {
  25. static void Main(string[] args)
  26. {
  27. B b = new B();
  28. b.Name = "李志伟";
  29. b.print();
  30. }
  31. }

(2)不能有静态(static)的抽象方法,也不能有静态的抽象属性!

15.接口(interface)

(1)接口的使用

  1. interface IA
  2. {
  3. void print();//抽象方法,不能使用public等修饰符
  4. string Name//抽象属性,也可使用抽象索引器
  5. {
  6. set;
  7. get;
  8. }
  9. }
  10. class B : IA
  11. {
  12. private string m_name;
  13. public void print()//不能使用override或new
  14. {
  15. Console.WriteLine(m_name);
  16. }
  17. public string Name//不能使用override或new
  18. {
  19. set { m_name = value; }
  20. get { return m_name; }
  21. }
  22. }
  23. class Program
  24. {
  25. static void Main(string[] args)
  26. {
  27. B b = new B();
  28. b.Name = "李志伟";
  29. b.print();
  30. }
  31. }

(2)接口里不能包含成员变量、构造器、析构器,接口的抽象方法不能使用修饰符(如:abstract、public等),因为抽象方法必须是public abstract。

(3)使用完全限定接口成员名(显示接口成员实现)

  1. interface IA
  2. {
  3. void print();
  4. }
  5. interface IB
  6. {
  7. void print();
  8. }
  9. class A : IA, IB
  10. {
  11. void IA.print()//显示接口成员实现,不能使用public等关键字,只能是private
  12. {
  13. Console.WriteLine("IA.print");
  14. }
  15. void IB.print()//显示接口成员实现,不能使用public等关键字,只能是private
  16. {
  17. Console.WriteLine("IB.print");
  18. }
  19. public void print()
  20. {
  21. Console.WriteLine("A.print");
  22. }
  23. }
  24. class Program
  25. {
  26. static void Main(string[] args)
  27. {
  28. A a = new A();
  29. ((IA)a).print();//使用IA接口访问,IA的print()
  30. ((IB)a).print();//使用IB接口访问,IB的print()
  31. a.print();//只能访问自己的print()
  32. }
  33. }

上面程序运行结果:IA.print  IB.print  A.print

(4)接口的复杂使用(复杂的多重继承)

(a)直观隐藏规则

  1. interface IA
  2. {
  3. void F();
  4. }
  5. interface IB : IA
  6. {
  7. new void F();//隐藏了IA的F()
  8. }
  9. interface IC : IA
  10. {
  11. void G();
  12. }
  13. interface IBC : IB, IC
  14. {
  15. }
  16. class Test : IBC
  17. {
  18. public void F()
  19. {
  20. Console.WriteLine("IB.F");//由于IB隐藏了IA的F(),所以这里实现的是IB的F()
  21. }
  22. public void G()
  23. {
  24. Console.WriteLine("IC.G");
  25. }
  26. }
  27. class Program
  28. {
  29. static void Main(string[] args)
  30. {
  31. Test t = new Test();
  32. t.F();
  33. ((IA)t).F();
  34. ((IB)t).F();
  35. ((IC)t).F();//值得注意,由于IB隐藏了IA的F(),所以这里调用的是IB的F()
  36. ((IBC)t).F();
  37. }
  38. }

上面程序运行结果:IB.F IB.F IB.F IB.F IB.F

(b)接口的重新实现

  1. interface IA
  2. {
  3. void print();
  4. }
  5. class A : IA
  6. {
  7. void IA.print()//接口的继承
  8. {
  9. Console.WriteLine("A.print");
  10. }
  11. }
  12. class B : A, IA
  13. {
  14. public void print()//接口的重新实现,将会覆盖接口的继承,所以A的print()被完全覆盖
  15. {
  16. Console.WriteLine("B.print");
  17. }
  18. }
  19. class Program
  20. {
  21. static void Main(string[] args)
  22. {
  23. B b = new B();
  24. ((IA)b).print();
  25. }
  26. }

上面程序运行结果:B.print

16.排序(IComparable与IComparer)

(1)基本数据类型的排序

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. int[] array = { 2, 3, 6, 9, 8, 4, 7, 5, 0 };
  6. Array.Sort(array);//排序方法
  7. foreach (int i in array)
  8. {
  9. Console.Write(i + " ");
  10. }
  11. }
  12. }

上面的程序运行结果:0 2 3 4 5 6 7 8 9

(2)自定义的类型的排序(实现IComparable接口)

  1. class A : IComparable
  2. {
  3. private string name;
  4. private int age;
  5. public A(string name, int age)
  6. {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public int CompareTo(object obj)//实现比较的方法
  11. {
  12. A temp;
  13. if (obj is A)
  14. {
  15. temp = obj as A;
  16. }
  17. else
  18. {
  19. throw new ArgumentException("类型不一致!");
  20. }
  21. return this.name.CompareTo(temp.name);//根据姓名排序
  22. }
  23. public override string ToString()
  24. {
  25. return "[" + name + " " + age + "]";
  26. }
  27. }
  28. class Program
  29. {
  30. static void Main(string[] args)
  31. {
  32. A[] array = new A[3];
  33. array[0] = new A("李志伟", 20);
  34. array[1] = new A("张三", 19);
  35. array[2] = new A("李四", 17);
  36. Array.Sort(array);//排序方法,对自定义类型进行排序
  37. foreach (A i in array)
  38. {
  39. Console.Write(i + " ");
  40. }
  41. }
  42. }

(3)为自定义的类定义排序类(IComparer接口)

  1. class A
  2. {
  3. private string name;
  4. private int age;
  5. public A(string name, int age)
  6. {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public string Name
  11. {
  12. get { return name; }
  13. }
  14. public int Age
  15. {
  16. get { return age; }
  17. }
  18. public override string ToString()
  19. {
  20. return "[" + name + " " + age + "]";
  21. }
  22. }
  23. class B : IComparer//专为类A设计的排序类
  24. {
  25. private static B b;
  26. private B()
  27. {
  28. }
  29. public static B GetB()
  30. {
  31. if (b == null)
  32. {
  33. b = new B();
  34. }
  35. return b;
  36. }
  37. public int Compare(Object x, Object y)//实现排序方法
  38. {
  39. A xa, ya;
  40. if ((x is A) && (y is A))
  41. {
  42. xa = x as A;
  43. ya = y as A;
  44. }
  45. else
  46. {
  47. throw new ArgumentException("类型不一致!");
  48. }
  49. return xa.Name.CompareTo(ya.Name);//根据姓名排序
  50. }
  51. }
  52. class Program
  53. {
  54. static void Main(string[] args)
  55. {
  56. A[] array = new A[3];
  57. array[0] = new A("李志伟", 20);
  58. array[1] = new A("张三", 19);
  59. array[2] = new A("李四", 17);
  60. Array.Sort(array, B.GetB());//排序方法
  61. foreach (A i in array)
  62. {
  63. Console.Write(i + " ");
  64. }
  65. }
  66. }

17.扩展方法

(1)说明

通过扩展方法,我们可以对已有类型做自己想做的相关扩展而不需要已有类型的源代码。扩展方法是通过额外的静态方法扩展现有的类型。也可以对String,Int,DataTable等类型的基础上增加一个或多个方法,使用时不需要去修改或编译类型本身的代码。

(2)例子

  1. public static class MyExtensions//静态的扩展类
  2. {
  3. public static int StringExtensions(this String str)//为String类增加一个方法
  4. {
  5. Console.WriteLine(str);
  6. return str.Length;
  7. }
  8. public static String StringJoin(this String str1, String str2)//为String类增加一个方法
  9. {
  10. Console.WriteLine(str1 + str2);
  11. return str1 + str2;
  12. }
  13. }
  14. class Program
  15. {
  16. static void Main(string[] args)
  17. {
  18. String s = "12345678";
  19. s.StringExtensions();//测试自定义的扩展方法
  20. s.StringJoin("000000000000000");//测试自定义的扩展方法
  21. }
  22. }

(3)注意

如果扩展方法包含参数,就可以在要扩展的类型(即第一个参数)以后顺序的添加扩展方法对应的参数既可,在调用的时候填写相应参数,不过请记住,第一个参数是要扩展的类型,其前面要加this关键字,在填写实参的时候并没有这个参数。

18.密封类和密封方法(sealed)

(1)Sealed修饰类不能被继承,sealed修饰方法不能被重写,类似Java的Final关键字。

19.yield return语句动态的返回集合

  1. class Program
  2. {
  3. static IEnumerable<string> GetEnumerator(int a, int b)
  4. {
  5. long d = 1;
  6. for (int i = 1; i <= b; i++)
  7. {
  8. d = a * d;
  9. yield return a + "的" + i + "次方是:" + d;//多次被执行
  10. }
  11. }
  12. static void Main(string[] args)
  13. {
  14. foreach (string s in GetEnumerator(2, 20))//遍历返回的集合
  15. {
  16. Console.WriteLine(s);
  17. }
  18. }
  19. }

20.多线程的应用

(1)多线程的基本使用

不需要传递参数,也不需要返回参数:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. for (int i = 0; i < 30; i++)
  6. {
  7. ThreadStart threadStart = new ThreadStart(Calculate);
  8. Thread thread = new Thread(threadStart);
  9. thread.Start();
  10. }
  11. Thread.Sleep(2000);
  12. Console.Read();
  13. }
  14. public static void Calculate()
  15. {
  16. DateTime time = DateTime.Now;//得到当前时间
  17. Random ra = new Random();//随机数对象
  18. Thread.Sleep(ra.Next(10,100));//随机休眠一段时间
  19. Console.WriteLine(time.Minute + ":" + time.Millisecond);
  20. }
  21. }

ThreadStart是一个委托,这个委托的定义为void ThreadStart(),没有参数与返回值。

需要传递单个参数:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. for (int i = 0; i < 30; i++)
  6. {
  7. ParameterizedThreadStart tStart = new ParameterizedThreadStart(Calculate);
  8. Thread thread = new Thread(tStart);
  9. thread.Start(i * 10 + 10);//传递参数
  10. }
  11. Thread.Sleep(2000);
  12. Console.Read();
  13. }
  14. public static void Calculate(object arg)
  15. {
  16. Random ra = new Random();//随机数对象
  17. Thread.Sleep(ra.Next(10, 100));//随机休眠一段时间
  18. Console.WriteLine(arg);
  19. }
  20. }

ParameterThreadStart委托定义为void ParameterizedThreadStart(object state),有一个参数但是没有返回值。

使用专门的线程类:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. MyThread mt = new MyThread(100);
  6. ThreadStart threadStart = new ThreadStart(mt.Calculate);
  7. Thread thread = new Thread(threadStart);
  8. thread.Start();
  9. //等待线程结束
  10. while (thread.ThreadState != ThreadState.Stopped)
  11. {
  12. Thread.Sleep(10);
  13. }
  14. Console.WriteLine(mt.Result);//打印返回值
  15. Console.Read();
  16. }
  17. }
  18. public class MyThread//线程类
  19. {
  20. public int Parame { set; get; }//参数
  21. public int Result { set; get; }//返回值
  22. //构造函数
  23. public MyThread(int parame)
  24. {
  25. this.Parame = parame;
  26. }
  27. //线程执行方法
  28. public void Calculate()
  29. {
  30. Random ra = new Random();//随机数对象
  31. Thread.Sleep(ra.Next(10, 100));//随机休眠一段时间
  32. Console.WriteLine(this.Parame);
  33. this.Result = this.Parame * ra.Next(10, 100);
  34. }
  35. }

使用线程类可以有多个参数与多个返回值,十分灵活!

使用匿名方法:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. int Parame = 100;//当做参数
  6. int Result = 0;//当做返回值
  7. //匿名方法
  8. ThreadStart threadStart = new ThreadStart(delegate()
  9. {
  10. Random ra = new Random();//随机数对象
  11. Thread.Sleep(ra.Next(10, 100));//随机休眠一段时间
  12. Console.WriteLine(Parame);//输出参数
  13. Result = Parame * ra.Next(10, 100);//计算返回值
  14. });
  15. Thread thread = new Thread(threadStart);
  16. thread.Start();//多线程启动匿名方法
  17. //等待线程结束
  18. while (thread.ThreadState != ThreadState.Stopped)
  19. {
  20. Thread.Sleep(10);
  21. }
  22. Console.WriteLine(Result);//打印返回值
  23. Console.Read();
  24. }
  25. }

使用匿名方法启动线程可以有多个参数和返回值,而且使用非常方便!

(2)如何判断线程已经运行完成

使用System.Threading.ThreadState枚举判断线程状态,与Thread.ThreadState 属性配合使用。

-------------------------------------------------------------------------------------------------------------------------------

来自为知笔记(Wiz)

时间: 2024-08-23 19:42:06

01.C#核心语法的相关文章

PHP核心语法总结

这些天学习了PHP的核心编程语法,PHP核心语法概括起来不多,大致分为php标签,语法规范.数据类型.变量.常量.当然还有预定义的,还有操作符.循坏等等,最后几天学习了函数,其中数组的常用函数非常多.例如array_merge.rand.asort.arsort这些,在日后项目中会用的比较多. 数组的函数里,foreach()与while-list-each()两个遍历数组的函数最为强大,不仅能解决访问数组的问题,而且它的返回值各有特点,可以灵活运用在往后数据库数据的处理中. 平时的应用PHP语

黑马程序员— OC核心语法之构造方法、Category分类、类的本质、description和SEL

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 上一章我们学习了OC的一些核心语法,初步了解了OC作为一门开发语言的一些较为深层次的知识.本章我们继续学习OC的核心语法,主要包括OC的构造方法,Category分类,类的本质及深入研究,以及description关键字和SEL关键字. 第一讲     构造方法 1. 构造方法 构造方法是用来初始化对象的方法,是一个对象方法,以减号"-"开头,构造方法其实就是init方法,初始化完毕

关情纸尾-----OC面对对象的核心语法

有点愧疚,这几个月荒废了,也浪费了很多时间. 接下来是我看的关于核心语法的一些笔记,可能不全也可能有错误,希望大家可以指出来. 一.点语法 点语法的本质是调用. 例如: Person *p = [Person new]; //赋值 p.age = 10; // 等价于[P setAge:10];调用setter //取值 int a = p.age;// 等价于[P age];调用getter 二.成员变量的作用域 @public  任何地方都能直接访问 @private 只能在当前类的对象方法

【zepto学习笔记01】核心方法$()(补)

前言 在很久之前,我们项目有一个动画功能,功能本身很简单,便是典型的右进左出,并且带动画功能 以当时来说,虽然很简单,但是受限于框架本身的难度,就直接使用了CSS3的方式完成了功能 当时主要使用transform与animation实现功能,并且用了一个settimeout执行回调,然后此事便不了了之了 但是出来混总是要还的,这不,最近相似的东西又提了出来,我们当然可以将原来的那套东西拿来用,但是看着那个settimeout总是不是滋味,因为这样捕捉回调的效果以及可能引起的BUG大家都懂,于是就

编译技术图式(第四章 语法分析)01文法和语法的定义

编译技术图式(第四章 语法分析)01文法和语法的定义 1.基本概念 1)词法规则: 哪些字符串合法或者不合法 字母表:语言允许使用字符的集合 词汇:由字符组成的有限串(字符串) 标识符:函数名,变量名等 2)语法规则: 句子:一个“词汇序列” 确定句子在形式上是否合法 提供句子的结构: if ( 表达式 ) 语句 else 语句 3)语法的表示: (1)自然语言描述 (2)形式化描述(BNF) (3)转换图(语法图) 2.形式化描述 终结符.非终结符.产生式 1)定义 2)产生式的表示    

[php入门] 2、基础核心语法大纲

1 前言 最近在学PHP,上节主要总结了PHP开发环境搭建<[php入门] 1.从安装开发环境环境到(庄B)做个炫酷的登陆应用>.本节主要总结PHP的核心基础语法,基本以粗轮廓写,可以算作核心大纲吧! 2 新建环境 1.配置根目录可通过修改配置文件 2.根目录用来存放应用程序的源码及资源 3.PHP的代码必须放在<?PHP    ?>中 4.变量只能以汉字.字母.下划线开头 5.输出:echo 6.编码问题:创建的文件都有编码,我们一般用UTF-8,但是系统默认的是其他编码,因此要

MySQL技术探索01实现SQL语法解析器

本文将介绍如何使用开源的语法和词法分析框架bison和flex来实现SQL解析器.出于技术学习的目的,本文做描述的微型SQL解析器仅能实现对微型SQL的语法解析. 1.MySQL中的SQL解析器 包括JDBC.ODBC.ADO等等关系数据库客户端应用开发框架在内的各种SDK,核心功能是帮助程序员简化各种客户端的数据库操作,同时将SQL语句通过网络形式发送给MySQL等关系数据库的服务器进程.MySQL服务器进行负责解析并执行这些SQL语句.SQL语句中的语法规则多种多样,MySQL服务器是如何实

OC语言-04-OC语言-核心语法

一.点语法 1> 基本使用 点语法本质上是set方法/get方法的调用 2> 使用注意 若出现在赋值操作符的右边,在执行时会转换成get方法 若出现在赋值操作符的左边,在执行时会转换成set方法 不能在set.get方法中用self使用点语法,会造成死循环 二.property和synthesize关键字 1> @property 作用 ① 自动生成某个成员变量的set方法和get方法 使用注意 ① 只能出现在@interface中 ② 可以使用逗号运算符为多个同类型的成员变量生成set

《Invert》开发日志01:核心玩法设计

前面提过,这个游戏的核心玩法基于我做的第一个Unity游戏,名字就叫<Invert>,现在在应用宝上面还能搜到.不过那个游戏也不是我原创的,它的玩法设计来自github上的一个开源项目(https://github.com/gorried/inverter),那时候我正在上培训班,它本来是我的一个课下练习.当时主要是为了熟悉游戏从制作到发布的流程,所以几乎完全模仿了原项目的设计,连方块的配色都没改(因为我觉得那配色挺好看的,还特意用Photoshop取了人家的色值). 但是现在回过头来看,这种