快速上手CS 常用关键字 abstract 可以和类、方法、属性、索引器及事件一起使用(成员变量、委托不能使用)
在类声明 中使用 abstract 修饰符以指示类只能是其他类的基类
在方法或属性声明 中使用 abstract 修饰符以指示此方法或属性不包含实现
抽象类特征
1、抽象类不能实例化
2、抽象类可以包含抽象方法和抽象访问器
3、不能用 sealed 修饰符修改抽象类,这意味着该类不能被继承
4、从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实现
5、在抽象类中可以定义静态方法
抽象方法特点
1、抽象方法是隐式的 virtual 方法
2、只允许在抽象类中使用 抽象方法声明
3、因为抽象方法声明不提供实现,所以没有方法体
4、实现由override方法提供,它是非抽象类的成员
5、在抽象方法声明中使用 static 或 virtual 修饰符是错误的
抽象属性特点
1、在静态属性上使用 abstract 修饰符是错误的
2、在派生类中,通过包括使用 override 修饰符的属性声明可以重写抽象的继承属性
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 abstract class A { public int a; public string [] arr; public delegate void ptr () ; public abstract int b{get ;set ;} public abstract void method0 () ; public abstract event ptr evt; public abstract string this [int index]{get ;set ;} public static int c; public static void method () { System.Console.WriteLine("method" ); } }
const 限定一个变量不允许被改变
1、用于修改字段或局部变量的声明,表示指定的字段或局部变量的值是常数 ,不能被修改
2、常数声明的类型指定声明引入的成员类型。常数表达式必须产生具有目标类型或可隐式转换为目标类型的值
3、常数表达式是在编译时可被完全计算的表达式。因此不能从一个变量中提取值来初始化常量
4、常数声明可以声明多个常数
5、不允许在常数声明中使用static修饰符 ,因为const默认为static
6、常数可以参与常数表达式:const int c = 5; const int d = c + 10;
others
as: 安全的类型转换
is: 检查对象是否与给定的类型兼容
base:基类
byte: 一个字节
checked: 检查数值是否溢出
decimal: 128位数据类型,适用于财务和货币计算:decimal myMonney = 99.9m;
enum:枚举:enum Days{Sun, Mon, Tue};
explicit: 强制类型转换
1 2 3 4 5 6 7 8 9 10 11 class A { ... }class B { public static explicit operator B (A a ) { return new B(a); } }
implicit: 隐式转换,方式同explicit
try/catch/throw/finally: 用于处理异常,也可以实现多层嵌套内直接跳转到最外层
fixed:放置GC重新定位可移动的变量
goto:直接跳转到对应标签位置
internal:声明的类型或者成员只能在同一程集内访问
lock:与线程有关
out:类似于ref,但只能用来将值从方法中传出
params:可变长参数,在声明方法时参数类型或者个数不确定时使用method(params Object[] objs)
readonly:动态常量,可在运行时赋值,可以被static修饰
sbyte: 有符号字节
sealed:被修饰的类或者方法不能被继承或者重写,密封方法必须对基类的虚方法进行重载,不能用来修饰成员变量
virtual: 用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写
override:提供从基类继承的成员的新实现,被重写的属性必须是virtual, abstract 或者override的
(函数和属性分为虚和非虚,只有虚方法才能被继承重写或者密封)
stackalloc: 在堆栈上分配内存块
struct: 结构体
uint, ulong, ushort: 无符号变量
volatile:字段可能被多个并发的执行线程修改
operator: 重载运算符
类、接口 定义类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A { public int a; public A (int b=0 ) { return ; } public static void Main () { A a = new A(); } ~A() { } }
类的继承:
1 2 3 4 5 6 7 class B : A { public B (int b ):base (b ) { base .a = b; } }
接口:
1 2 3 4 interface IMyInterface { void method () ; }
接口支持多重继承,类不支持
文件处理 FileStream类 用于文件的读写和关闭
1 2 3 4 5 6 7 FileStream fs = new FileStream(filename, FileMode.Open | Append | Create, FileAccess.Read | Write); fs.WriteByte(); fs.Write(array, offset, count); fs.Read(array, offset, count); fs.ReadByte(); fs.Seek(offset, System.IO.SeekOrigin.Current); fs.Dispose();
StreamReader类 文本文件读取
1 2 3 StreamReader reader = new StreamReader(filename); reader.Read(); reader.ReadLine();
StreamWriter类 文本文件写入
用法类似reader
命名空间 命名空间 的设计目的是提供一种让一组名称与其他名称分隔开的方式。在一个命名空间中声明的类的名称与另一个命名空间中声明的相同的类的名称不冲突。
常用命名空间:
1 2 3 4 using System;using System.IO; using System.Collections; using System.Collections.Generic;
特性和反射 特性(Attribute) 是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义 特性和自定义 特性。
常用特性:
Conditional
这个预定义特性标记了一个条件方法 ,其执行依赖于指定的预处理标识符。
它会引起方法调用的条件编译,取决于指定的值,比如 Debug 或 Trace 。例如,当调试代码时显示变量的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #define DEBUG using System; ...public class MyClass { [Conditional("DEBUG" ) ] public static void method (string msg ) { ... } }class Test { public static void Main () { Myclass.Message("DEBUG" ); } }
Obsolete
这个预定义特性标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为 obsolete(过时的)。
1 2 3 4 [Obsolete( message, iserror ) ]
其中:
参数 message ,是一个字符串,描述项目为什么过时以及该替代使用什么。
参数 iserror ,是一个布尔值。如果该值为 true,编译器应把该项目的使用当作一个错误。默认值是 false(编译器生成一个警告)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 using System;public class MyClass { [Obsolete("Don't use OldMethod, use NewMethod instead" , true) ] static void OldMethod () { Console.WriteLine("It is the old method" ); } static void NewMethod () { Console.WriteLine("It is the new method" ); } public static void Main () { OldMethod(); } }
自定义特性和反射
反射指程序可以访问、检测和修改它本身状态或行为的一种能力。
程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。
您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
优缺点
优点:
反射提高了程序的灵活性和扩展性。
降低耦合性,提高自适应能力。
它允许程序创建和控制任何类的对象,无需提前硬编码目标类 。
缺点:
性能问题 :使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。
用途
反射(Reflection)有下列用途:
它允许在运行时查看特性(attribute)信息 。
它允许审查集合中的各种类型,以及实例化这些类型。
它允许延迟绑定的方法和属性 (property)。
它允许在运行时创建新类型,然后使用这些类型执行一些任务。
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 using System;using System.Reflection;namespace BugFixApplication { [AttributeUsage #region//定义了特性能被放在那些前面 (AttributeTargets.Class |//规定了特性能被放在class的前面 AttributeTargets.Constructor |//规定了特性能被放在构造函数的前面 AttributeTargets.Field |//规定了特性能被放在域的前面 AttributeTargets.Method |//规定了特性能被放在方法的前面 AttributeTargets.Property,//规定了特性能被放在属性的前面 #endregion AllowMultiple = true) ] public class DeBugInfo : System.Attribute { private int bugNo; private string developer; private string lastReview; public string message; public DeBugInfo (int bg,string dev,string d ) { this .bugNo = bg; this .developer = dev; this .lastReview = d; } #region //定义对应的调用,返回对应值value public int BugNo { get { return bugNo; } } public string Developer { get { return developer; } } public string LastReview { get { return lastReview; } } public string Message { get {return message;} set {message = value ;} } } #endregion [DeBugInfo(45, "Zara Ali" , "12/8/2012" , Message = "Return type mismatch" ) ] [DeBugInfo(49, "Nuha Ali" , "10/10/2012" , Message = "Unused variable" ) ] class Rectangle { protected double length; protected double width; public Rectangle (double l,double w ) { length = l; width = w; } [DeBugInfo(55, "Zara Ali" , "19/10/2012" , Message = "Return type mismatch" ) ] public double GetArea () { return length * width; } [DeBugInfo(56, "Zara Ali" , "19/10/2012" ) ] public void Display () { Console.WriteLine("Length: {0}" , length); Console.WriteLine("Width:{0}" , width); Console.WriteLine("Area:{0}" , GetArea()); } } class ExecuteRectangle { static void Main (string [] args ) { Rectangle r = new Rectangle(4.5 , 7.5 ); r.Display(); Type type = typeof (Rectangle); foreach (Object attributes in type.GetCustomAttributes(false )) { DeBugInfo dbi = (DeBugInfo)attributes; if (null != dbi) { Console.WriteLine("Bug on: {0}" , dbi.BugNo); Console.WriteLine("Developer: {0}" , dbi.Developer); Console.WriteLine("Last REviewed: {0}" , dbi.LastReview); Console.WriteLine("Remarks: {0}" , dbi.Message); } } foreach (MethodInfo m in type.GetMethods()) { foreach (Attribute a in m.GetCustomAttributes(true )) { DeBugInfo dbi = a as DeBugInfo; if (null !=dbi) { Console.WriteLine("BugFixApplication no: {0},for Method: {1}" , dbi.BugNo, m.Name); Console.WriteLine("Developer:{0}" , dbi.Developer); Console.WriteLine("Last Reviewed: {0}" , dbi.LastReview); Console.WriteLine("Remarks: {0}" , dbi.Message); } } } Console.ReadKey(); } } }
属性 属性(Property)是域(Field)的扩展,且可使用相同的语法来访问。它们使用 访问器(accessors) 让私有域的值可被读写或操作。
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public int a{get ;} int a{get ;set ;} public int a{get ;private set ;} class Program { public abstract class Person { public abstract string Name { get ; set ; } public abstract int Age { get ; set ; } } public class Student : Person { public string Code { get ; set ; } = "N.A" ; public override string Name { get ; set ; } = "N.A" ; public override int Age { get ; set ; } = 0 ; } }
委托和事件 委托 C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。
声明和实例化委托:
1 2 public delegate int MyDelegate (string s ) ; MyDelegate del1 = new MyDelegate(str);
委托的多播
委托对象可使用 “+” 运算符进行合并 。一个合并委托调用它所合并的两个委托。只有相同类型的委托可被合并 。**”-“ 运算符可用于从合并的委托中移除组件委托**。使用委托的这个有用的特点,您可以创建一个委托被调用时要调用的方法的调用列表。这被称为委托的 多播(multicasting) ,也叫组播。
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 using System;delegate int NumberChanger (int n ) ;namespace DelegateAppl { class TestDelegate { static int num = 10 ; public static int AddNum (int p ) { num += p; return num; } public static int MultNum (int q ) { num *= q; return num; } public static int getNum () { return num; } static void Main (string [] args ) { NumberChanger nc; NumberChanger nc1 = new NumberChanger(AddNum); NumberChanger nc2 = new NumberChanger(MultNum); nc = nc1; nc += nc2; nc(5 ); Console.WriteLine("Value of Num: {0}" , getNum()); Console.ReadKey(); } } }
委托可以作为函数的参数被函数内部调用
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 using System;using System.IO;namespace DelegateAppl { class PrintString { static FileStream fs; static StreamWriter sw; public delegate void printString (string s ) ; public static void WriteToScreen (string str ) { Console.WriteLine("The String is: {0}" , str); } public static void WriteToFile (string s ) { fs = new FileStream("c:\\message.txt" , FileMode.Append, FileAccess.Write); sw = new StreamWriter(fs); sw.WriteLine(s); sw.Flush(); sw.Close(); fs.Close(); } public static void sendString (printString ps ) { ps("Hello World" ); } static void Main (string [] args ) { printString ps1 = new printString(WriteToScreen); printString ps2 = new printString(WriteToFile); sendString(ps1); sendString(ps2); Console.ReadKey(); } } }
可以使用匿名方法创建委托实例:
1 2 3 4 NumberChanger nc = delegate (int x) { Console.WriteLine("Anonymous Method: {0}" , x); };
事件 事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。C# 中使用事件机制实现线程间的通信。
通过事件使用委托
事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。
发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。
订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。
声明事件
1 2 public delegate void BoilerLogHandler (string status ) ; public event BoilerLogHandler BoilerEventLog;
实例:
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;namespace SimpleEvent { using System; public class EventTest { private int value ; public delegate void NumManipulationHandler () ; public event NumManipulationHandler ChangeNum; protected virtual void OnNumChanged () { if ( ChangeNum != null ) { ChangeNum(); }else { Console.WriteLine( "event not fire" ); Console.ReadKey(); } } public EventTest () { int n = 5 ; SetValue( n ); } public void SetValue ( int n ) { if ( value != n ) { value = n; OnNumChanged(); } } } public class subscribEvent { public void printf () { Console.WriteLine( "event fire" ); Console.ReadKey(); } } public class MainClass { public static void Main () { EventTest e = new EventTest(); subscribEvent v = new subscribEvent(); e.ChangeNum += new EventTest.NumManipulationHandler( v.printf ); e.SetValue( 7 ); e.SetValue( 11 ); } } }
集合 集合(Collection)类是专门用于数据存储和检索的类。这些类提供了对栈(stack)、队列(queue)、列表(list)和哈希表(hash table)的支持。大多数集合类实现了相同的接口。
集合(Collection)类服务于不同的目的,如为元素动态分配内存,基于索引访问列表项等等。这些类创建 Object 类的对象的集合。在 C# 中,Object 类是所有数据类型的基类。
常用集合:
ArrayList:可被单独索引的有序集合
Hashtable:可以使用键来访问集合中的元素
SortedList:可以使用键和索引来访问列表中的项
Stack:堆栈
Queue: 队列
BitArray: 点阵列,使用值1和0来表示二进制数组,当您需要存储位,但是事先不知道位数时,则使用点阵列。您可以使用整型索引 从点阵列集合中访问各项,索引从零开始
泛型 泛型(Generic) 允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。
您可以通过数据类型的替代参数编写类或方法的规范。当编译器遇到类的构造函数或方法的函数调用时,它会生成代码来处理指定的数据类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class MyGenericArray <T > { private T[] array; public MyGenericArray (int size ) { array = new T[size + 1 ]; } public T getItem (int index ) { return array[index]; } public void setItem (int index, T value ) { array[index] = value ; } }
泛型特性
它有助于您最大限度地重用代码、保护类型的安全以及提高性能。
您可以创建泛型集合类。.NET 框架类库在 System.Collections.Generic 命名空间中包含了一些新的泛型集合类。您可以使用这些泛型集合类来替代 System.Collections 中的集合类。
您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托 。
您可以对泛型类进行约束以访问特定数据类型的方法。
关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取 。
常用泛型
Dictionary: 键和值的集合
HashSet : 值的集合
LinkedList: 双重链接列表
List :可通过索引访问的对象的强类型列表
Queue:队列
SortedDictionary:根据键进行排序的键/值对的集合
SortedList:同上
SortedSet:表示按排序顺序维护的对象的集合
Stack:栈