C#程序设计教程-语法速览
《C#程序设计教程-第二版-蒙祖强-清华大学出版社》 C# 介绍 - C# 指南 | Microsoft Docs
学校定的C#教程,从零开始那种。 从开始到P130是基础部分,P130-P250是GUI部分,P250往后是高级特性和程序设计应用。 基础部分比较像C++和Java的杂交语法,可以光速看完。 然后把其中一些特性或者生疏点在此摘记一下。
P31 : 2.5.2-枚举类型 定义
1 2 3 enum weekdays {Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}weekdays day; day = weekdays.Sunday;
枚举类型在定义时按照从左到右的顺序依次给枚举元素分配了整数值:0, 1, 2, … 。利用这些值,可以灵活访问枚举类型变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 static void Main (String[] args ) { weekdays day; day = weekdays.Sunday; Console.WriteLine(day); day++;Console.WriteLine(day); day++;Console.WriteLine(day); day++;Console.WriteLine(day); day++;Console.WriteLine(day); day++;Console.WriteLine(day); day++;Console.WriteLine(day); day++;Console.WriteLine(day); Console.ReadKey();
P34 : 2.6.3-多维数组 定义
1 2 3 int [ , ] a;a = new int [2 ,3 ]; int [ , ] a = new int [2 ,3 ];
定义时赋值
1 2 3 4 int [ , ] a = new int [2 ,3 ]{{1 ,2 ,3 ],{4 ,5 ,6 }};
P52 : 3.6.2-foreach遍历哈希表、枚举 foreach特性和Java、Python3的foreach(int a : a[])、for i in range一致
1 2 3 4 int [] a = {1 ,2 ,3 ,4 };foreach (int i in a){ Console.WriteLine(i); }
Hashtable是命名空间System.Collections中的一个容器,它类似于Python中的字典。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Collections;namespace foreachExam { class Program { static void Main (string [] args ) { Hashtable ht = new Hashtable(); ht.Add(201001 , "张三" ); ht.Add(201002 , "李四" ); ht.Add(201003 , "王五" ); ht.Add(201004 , "赵六" ); Console.WriteLine("学号为奇数的学生:" ); Console.WriteLine("---------------" ); Console.WriteLine("学号 姓名" ); foreach (int stuid in ht.Keys) { if ((stuid + 1 ) % 2 == 0 ) Console.WriteLine(stuid+" " +ht[stuid]); } Console.ReadLine(); } } }
typeof()获取类型的System.Type对象,Enum.GetValues()用于获取指定枚举类型的枚举值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace foreachEnum { class Program { enum weeddays { Sundays,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}; static void Main (string [] args ) { foreach (weeddays item in Enum.GetValues(typeof (weeddays))) { Console.WriteLine(item); } Console.ReadLine(); } } }
P62 : 4.1.1-运算符重载 从C++那里学过来的运算符重载。
对象是引用传参。所以最后return new出来的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace InmaginaryNumber { class Complex { double Rp, Ip; public double getRp ( ) { return Rp; } public double getIp ( ) { return Ip; } public Complex ( ) { Rp = Ip = 0 ; } public Complex (double Rp, double Ip ) { this .Rp = Rp; this .Ip = Ip; } public static Complex operator +(Complex c1, Complex c2) { Complex c = new Complex(c1.Rp + c2.Rp, c1.Ip + c2.Ip); return c; } public static Complex operator -(Complex c1, Complex c2) { Complex c = new Complex(c1.Rp - c2.Rp, c1.Ip - c2.Ip); return c; } public static Complex operator -(Complex c) { Complex c2 = new Complex(-c.Rp, -c.Ip); return c2; } public static implicit operator Complex (string s ) { s = s.Trim().TrimEnd('i' ); s = s.Trim().TrimEnd('*' ); string [] digits = s.Split('+' , '-' ); Complex c; c = new Complex(Convert.ToDouble(digits[0 ]), Convert.ToDouble(digits[1 ])); return c; } public String putIN ( ) { String output = Convert.ToString(Rp) + "+" + Convert.ToString(Ip) + "*i" ; return output; } } class Program { static void Main (string [] args ) { Complex c1 = new Complex(); Complex c2 = new Complex(1 , 2 ); Console.WriteLine("c1=" +c1.putIN()); Console.WriteLine("c2=" +c2.putIN()); Complex c3 = "100+200*i" ; Console.WriteLine("c3=" +c3.putIN()); Complex c4 = c2 - c1 + (-c3); Console.WriteLine("c4=" +c4.putIN()); Console.ReadLine(); } } }
P71 : 4.2.3-类的构造和析构 C#有垃圾回收了!!!C++学着点。非必要可不写析构。 另外,C#默认类成员属性私有。 C#没有指针,这里使用类创建单向链表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace linkUsingClass { public class link_node { public int data; public link_node next; public link_node (int data ) { this .data = data; } } class Program { static void Main (string [] args ) { link_node head, point, point_bak; point = new link_node(1 );head = point; point_bak = point; point = new link_node(2 ); point_bak.next = point; point_bak = point; point = new link_node(3 ); point_bak.next = point; point_bak = point; point = new link_node(4 ); point_bak.next = point; point_bak = point; point = new link_node(5 ); point_bak.next = point; point_bak = point; point = head; while (point != null ) { Console.WriteLine(point.data); point = point.next; } point = head; Console.ReadKey(); } } }
P72 : 4.2.4-类的属性 类的属性定义类似于javabean,是对成员变量的一种拓展。 javabean的作用:
1、所有属性为private 2、提供默认构造方法 3、提供getter和setter 4、实现serializable接口,用于对象的序列化和反序列化
我能看到最直接的作用是控制变量的读写权限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace ConsoleApp1 { class X { int x,y,z; public X ( ) { x = 1 ;y = 2 ;z = 3 ; } public int atx { get { return x; } set { x = value ; } } public int aty { get { return x; } } public int atz { set { x=value ; } } } class Program { static void Main (string [] args ) { X meber=new X(); meber.atx = 100 ; Console.WriteLine("x={0}" ,meber.atx); Console.WriteLine("y={0}" ,meber.aty); meber.atz = 300 ; } } }
P76 : 4.2.6-成员方法的四种参数类型 回顾
java传参:基本类型外向内单向传参,数组可修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import java.util.Arrays;class param { static int [] a={1 ,3 ,4 ,2 ,5 }; static int aa=10000 ; static private void change_value (int [] a,int aa) { System.out.println("--形参改变的方法内参数--" ); Arrays.sort(a); aa+=1 ; print_array(a,aa); } static private void print_array (int [] a,int aa) { for (int i : a){ System.out.print(i+" " ); } System.out.println(aa); } public static void main (String[] args) { change_value(a,aa); System.out.println("--方法块父级域参数,类静态--" ); print_array(a,aa); int [] b={1 ,3 ,4 ,2 ,5 }; int bb=10000 ; change_value(b,bb); System.out.println("--方法块父级域参数--" ); print_array(b,bb); } }
python传参:基本类型外向内单向传参,数组可修改。
1 2 3 4 5 6 7 8 9 10 aa=[1 ,2 ,3 ,4 ,5 ] a=10000 def change (list_a,int_a ): list_a.append(1 ) int_a+=1 print("方法内" ,list_a,int_a) change(aa,a) print("同块 " ,aa,a)
C#的传参
值类型参数。和常见语言的方法调用参数特性一致(java,python)。基本变量在方法内有自己的生存周期。
引用型参数ref。有点像C++的传引用,方法内外双向传参。
输出型参数out。C#新类型,方法块内向外传值,因此方法内必须对值进行初始化。
输入型参数in。形参成为实参的别名。必须是变量。
数组型参数params。C#新类型,数组参数可以省去定义变量名,可以一次传入若干变量。
这里in参数书上没提,补充一下:in 参数修饰符 - C# 参考 | Microsoft Docs ref
修饰符,指定参数由引用传递,可以由调用方法读取或写入。out
修饰符,指定参数由引用传递,必须由调用方法写入。in
修饰符,指定参数由引用传递,可以由调用方法读取,但不可以写入。
当我们传递一个数组给一个方法时,参数数组的元素可以被改变 ,出了方法继续使用,但new出来的数组如果不return的话会被垃圾回收。 这一点我们想到java的传参。实际上,java传参是值传递。C#既有值传递也有引用传递。
java传参:
如果参数是基本类型,传递的是基本类型的字面量值的拷贝。 如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。
当你new一个新对象赋值给“copy”变量名后,“copy”修改的是new出来的地址。出函数后,“origin”查看的值还是原来的地址。java的传参是值传递。
Java 到底是值传递还是引用传递? - 知乎 (zhihu.com)
一个例子看懂C#传参:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace @ref { class Program { public static void change_value (int i ,int [] j ) { i += 10000 ; for (int ii = 0 ; ii < j.Length; ii++) { j[ii] += 10000 *(ii+1 ); } } public static void change_ref (ref int i,ref int [] j ) { i += 10000 ; for (int ii = 0 ; ii < j.Length; ii++) { j[ii] += 10000 * (ii + 1 ); } } public static void change_out (out int i,out int [] j ) { i = 10000 ; j =new int []{ 10000 ,20000 ,30000 }; } public static void change_params (params int [] j ) { for (int ii = 0 ; ii < j.Length; ii++) { j[ii] += 10000 * (ii + 1 ); } } public static void change_value (int [] j ) { j = new int [] { 10000 , 20000 , 30000 }; } public static void output (int i,int [] j ) { Console.WriteLine(i); foreach (int jj in j) { Console.Write("{0} " ,jj); } Console.WriteLine(); } public static void init (out int i,out int [] j ) { i = 0 ; j =new int []{ 0 ,0 ,0 }; } static void Main (string [] args ) { int i; int [] j; init (out i, out j); Console.WriteLine("原值:" ); output(i, j); init (out i, out j); change_value(i, j); Console.WriteLine("常规值参数" ); output(i, j); init (out i, out j); change_ref(ref i, ref j); Console.WriteLine("ref型参数" ); output(i, j); init (out i, out j); change_out(out i, out j); Console.WriteLine("out型参数" ); output(i, j); init (out i, out j); change_params(j); Console.WriteLine("params型参数" ); output(i, j); init (out i, out j); change_params(0 , 0 , 0 ); change_value(j); Console.WriteLine("new出的对象出了方法就失联了" ); output(i, j); Console.ReadKey(); } } }
P78 : 4.3.1-继承 C#比起C++少了指针和多重继承。赋值兼容大体还是按照C++那套来的。
重载
不能重载静态成员方法
方法名相同,参数表不同,不看返回值类型
多态
编译时多态:方法重载
运行时多态:重写虚方法
继承
子类作基类使用时,子类使用从基类继承来的属性和方法,无视隐藏
子类使用基类的构造方法,构造的是来自基类的属性,可被新同名属性隐藏
方法里,子类的this和可以复写基类的this。
类被继承后,子类包含:新定义的属性和方法+重写基类的属性和方法+继承来自基类的属性和方法; 重写基类的属性和方法后,子类继承过来的属性和方法不是被覆盖,而是被隐藏。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Success { class Shape { private String name = "形状" ; protected double pi; public Shape ( ) { pi = 3.14 ; } public Shape (double pi ) { this .pi = pi; } public void show_name ( ) { Console.WriteLine(this .name); } public virtual double circle_area (double len, double pi = 3.14 ) { return 0 ; } } class Circle :Shape { private String name = "圆" ; new public double pi=3 ; public double len; public Circle ( ) { pi = 3.1415926535 ; len = 1 ; } public Circle (double len,double pi ) :base (pi ) { Console.WriteLine("--圆的带参构造--" ); Console.WriteLine("pi= {0}" , pi); Console.WriteLine("this.pi= {0}" , this .pi); Console.WriteLine("base.pi= {0}" , base .pi); Console.WriteLine("--------------" ); this .len = len; } public void show_name ( ) { Console.WriteLine(this .name); } public override double circle_area (double len, double pi ) { double area = pi * len * len; return area; } } class Program { static void show (Shape shape ) { shape.show_name(); } static void Main (string [] args ) { Shape shape = new Shape(); shape.show_name(); show(shape); Circle circle = new Circle(); circle.show_name(); show(circle); Circle circle2=new Circle(10 ,3.1514 ); Shape shape2 = circle2; shape2.show_name(); Console.WriteLine(circle2.len); Console.WriteLine(circle2.pi); Console.WriteLine(circle2.circle_area(circle2.len,circle2.pi)); Console.ReadLine(); } } }
P86 : 4.5.1-接口 定义:
接口成员不允许修饰符,默认公有成员。 成员可以分为四类:方法、属性、事件和索引器,不包含成员变量。
1 2 3 4 5 6 7 interface I { void f (int x ) ; int att{ get ; set ; } event EventHandler OnDraw; string this [int index] { get ; set ; } }
C#通过对接口的多重继承实现,来达到C++里多重继承的效果。实现过程需要满足所有方法的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 interface I1 { void f (int x ) ; int att { get ; set ; } event EventHandler OnDraw; string this [int index] { get ; set ; } } interface I2 { void g ( ) ; } public class A : I1 , I2 { private string [] strs = new string [100 ]; public void g ( ) { } public void f (int x ) { } public event EventHandler OnDraw { add { } remove { } } public int att { get { return 1 ; } set { } } public string this [int index] { get { if (index <=0 || index >= 100 ) return "" ; return strs[index]; } set { if (!(index < 0 || index >= 100 )) strs[index] = value ; } } }
P88 : 4.6-委托
解释: 函数指针。
作用: 方法回调。通俗来说就是:可以让一个方法伪装成一个对象,作为参数被其它方法调用。 个人感觉在不同类的方法耦合调用的情景下,这东西很方便。 b.function(new Delegate(A.function));
定义:
1 属性 修饰符 delegate 返回类型 委托类型名(参数表);
属性、修饰符:new、public、internal、protected、private。
实例化:
以下例子中,fg是a.f的委托;static_fg是A.g的委托。
条件: 参数表相同,返回类型相同。
组合委托: 同类型委托之间可以使用 + - 运算; 必须是同类型的委托才能组合,(同返回类型,同参数表); 委托列表所有委托统一使用组合委托传入的参数; 带返回的委托组合在一起时,组合委托返回的是委托列表最后一个委托的返回值。
1 2 3 4 5 6 7 8 9 fun([delegate_fun],s1,s2) { | | "class_a.fun"(s1,s2) } ---------------------------- fun( object_? ,s1,s2) { | | class_a.fun(s1,s2) }
如上图,使用委托[上],和传入对象[下]。使用委托仅限对象某一特定方法进入,相对来说更加安全。
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace simpledelegate { delegate void MyDelegate (string s ) ; class A { public void f (string msg ) { Console.WriteLine("方法f:" +msg); } public static void static_f (string msg ) { Console.WriteLine("方法static_f:" +msg); } } class B { public void h (MyDelegate m ) { m("这里是B,使用委托偷来了A的方法" + m.Method.Name); } } delegate string MyDelegateWithReturn (string s ) ; class C { public string g (string msg ) { return "方法g:" + msg; } public static string static_g (string msg ) { return "方法static_g:" + msg; } } class Program { static void Main (string [] args ) { MyDelegate static_fd = new MyDelegate(A.static_f); A a = new A(); MyDelegate fd = new MyDelegate(a.f); static_fd("A.static_f委托给static_fd" ); A.static_f("原来的A.static_f" ); fd("a.f委托给fd" ); a.f("原来的a.f" ); B b = new B(); b.h(fd); b.h(static_fd); MyDelegate togather_f = fd + static_fd; togather_f("无返回委托组合" ); C c = new C(); MyDelegateWithReturn static_fg = new MyDelegateWithReturn(C.static_g); MyDelegateWithReturn fg = new MyDelegateWithReturn(c.g); MyDelegateWithReturn togather_g = fg + static_fg; Console.WriteLine(togather_g("带返回委托组合" )); Console.ReadLine(); } } }
P96 : 4.7-泛型类 字面意思,支持各种类型的类。
定义一个函数,使其能交换两个参数的值,参数类型包括数组、对象、值等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace generic { class Program { class B <T > { public static void swap (ref T x,ref T y ) { T t = x; x = y; y = t; } } static void Main (string [] args ) { int a, b; a = 100 ;b = 200 ; Console.WriteLine("交换前:a={0},b={1}" ,a,b); B<int >.swap(ref a, ref b); Console.WriteLine("交换后:a={0},b={1}" ,a,b); Console.WriteLine("----------------------" ); string s1, s2; s1 = "西游记" ;s2 = "红楼live" ; Console.WriteLine("交换前:s1={0},s2={1}" ,s1,s2); B<string >.swap(ref s1, ref s2); Console.WriteLine("交换后:s1={0},s2={1}" ,s1,s2); Console.ReadKey(); } } }
泛型类用的多的还是泛型数组List类。特性较多,不抄了,直接搬库:
List Class (System.Collections.Generic) | Microsoft Docs
P110 : 4.9-命名空间 1 2 3 4 namespace 命名空间名 { 命名空间成员; }
命名空间可以是任意合法的标识符,命名空间成员通常是类,还可以是接口、枚举、委托、其它命名空间。 命名空间的修饰符为隐含的public类型,不能在声明时显式指定任何修饰符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using static System.Math;namespace Outlander { class A { static public void print ( ) { Console.WriteLine("this is Outlander.classA.print()" ); } } } namespace Here { using Out = Outlander.A; class A { static public void print ( ) { Console.WriteLine("this is Here.classA.print()" ); } } class Program { static void Main (string [] args ) { Console.WriteLine(PI); Outlander.A.print(); Out.print(); A.print(); Console.ReadLine(); } } }
常规导入:using Outlander; 相当于:import Outlander.*;
其它实用方式:
using指令:引入命名空间
1 2 using System;using Namespace1.SubNameSpace;
using static 指令:无需指定类型名称即可访问其静态成员的类型
1 2 using static System.Math;Console.WriteLine(PI);
起别名
using语句:将实例与代码绑定
using 语句 - C# 参考 | Microsoft Docs
1 2 3 using StringReader left = new StringReader(numbers), right = new StringReader(letters);
P120 : 5.1-异常 常用异常类:
类
介绍
ArithmeticException
在进行算术运算时可能产生的异常,是DivideByZeroException和OverflowException的基类
ArrayTypeMismatchException
但储存元素类型与数组元素类型不匹配而导致储存失败产生此异常
Exception
所有异常类的基类,可捕获所有异常
FormatException
参数格式错误而引发的异常
DivideByZeroException
当用零除一个整数数据时会产生此异常
IndexOutOfRangeException
用一个小于零或者大于数组边界的下标来访问一个数组元素时会产生此异常
IOException
该类用户处理进行文件输入输出操作所引发的异常
NullReferenceException
试图以null作为对象名来引用对象的成员会产生此异常
OutOfMemeryException
当使用new来申请内存而失败时会产生此异常
OverflowException
但选中的上下文中所进行的算术运算、类型运算等而导致存储单元溢出会产生此异常
SqlException
SQL操作引发的异常
TypeInitializationException
静态构造函数抛出异常且没有任何catch结构来捕获它时会产生此异常
注意:
Message:string类型的只读属性,包含异常原因描述。
InnerException:Exception类型的只读属性,如果其值为null,表明异常不是由另一个异常引发,而是由系统内部产生或者根据相关条件抛出;如果不是null,表示当前异常是对另一个异常的回应而被抛出,“另一个异常”则保存在InnerException属性中 。
catch (异常类 对象名){ … }中的 (异常类 对象名)可以省略,即catch { … }。如果省略该部分,不管在try中产生什么异常,程序都会转向执行catch中的代码,这种情况无法获取此异常的任何信息。
当try语句块中可能产生多个异常,遇到第一个异常后直接进入catch。此时若使用多个catch结构捕获,存在catch块顺序上的要求。派生类异常的catch块必须放到基类catch块的前面,因为基类catch块的捕获范围更大 。如果两catch块异常同级则顺序随意。
使用try-catch-finally结构时,哪怕catch块最后要执行return语句(try-catch(return)-finally),依然会执行finally块。
异常抛出
直接抛出,异常重发 throw e;
使用捕获的异常创建新的异常后抛出 throw new Exception([参数表]); —或者— Exception 异常对象=new Exception([参数表]); throw 异常对象;
直接抛出和二次打包的差别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace @throw { class testException { public void mistake ( ) { int n = 1 ; int m = 1 ; try { n = n / (n - m); Console.WriteLine("无任何异常" ); } catch(Exception e) { throw new Exception("mistake():" + e.Message, e); } } } class Program { static void Main (string [] args ) { testException te = new testException(); try { te.mistake(); } catch (Exception e) { Console.WriteLine("当前捕获的异常:" +e.Message); Console.WriteLine("当前异常内部异常(原异常)" + e.InnerException.Message); } finally { Console.ReadLine(); } } } }
异常的运用实例:用户自定义异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MyException { class UserException : Exception { public UserException ( ) { } public UserException (string ms ) : base (ms ) { } public UserException (string ms, Exception inner ) : base (ms, inner ) { } } class student { private string name; private double score; public void setInfo (string name,double score ) { if (name.Length > 8 ) { throw (new UserException("姓名长度超过8个字节" )); } if (score < 0 || score > 100 ) { throw (new UserException("非法的分数" )); } this .name = name; this .score = score; } } class Program { static void Main (string [] args ) { student s = new student(); try { s.setInfo("张三" ,999 ); }catch(Exception e) { Console.WriteLine("产生异常:{0}" ,e.Message); Console.ReadLine(); } } } }
P133 : 6.1-简易文本编辑器 文本编辑器包含文件打开和保存的操作,使用到系统的一个轮子:openFileDialog和saveFileDialog。课本代码有误,或只给出部分代码(将部分变量初始化代码写在外层的窗体初始化函数中),或课本过时(2010出版),说明一下:
1 2 3 4 5 6 7 8 9 10 private void openfileToolStripMenuItem_Click (object sender,EventArgs e ) { OpenFileDialog open=new OpenFileDialog(); open.Fileter="txt files(*.txt) | *.txt" ; if (open.showDialog()==DialogResult.OK) { richTextBox1.LoadFile(open.FileName,RichTextBoxStreamType.PlainText); } }
此外,第六章大都是组件和控件的介绍,实在没啥必要精读,用时拖着玩两下就会了,IDE代码补全里的介绍甚至比课本详细。
咳咳,说来真不好意思。平时作业写完要么学高数去了,要么玩游戏去了,没心情更博客了,拖到现在。本来是初学记录的,目前C#大作业都整完了。
剩下还有这些东西要补充的:
P208 : 7.2-目录 P212 : 7.3-文件 P247 : 9.1-多线程 P275 : 10.1-数据库 P312 : 11.1-ASP.NET Web
to be continue…
以后有缘再更到新文章里。 此文完结。 说到大作业,其实我只把目录、文件、数据库看了一遍,多线程和网页ASP没学,重点学了下treeView和DataGridView两个控件,连了下SQL Server,写了个学生管理系统,完了。 这个学期的C#就学到这里。 准备期末答辩了。
以后还是会细说一下C#多线程的。