1.C#的数据类型:值类型和引用类型。
值类型:把变量的值存在栈中,基本数据类型就是值类型,包括整型,浮点型,bool型,字符型,枚举型。
引用类型:引用类型会在栈中创建一个引用变量,在堆中建立对象本身,把对象所在内存的首地址赋给引用变量
2.委托:委托类似与C,C++中的函数指针,他存储的是和签名和返回类型相同的方法的地址。委托在使用时的三步,声明委托,实例委托,调用委托,调用委托时,委托包含的所有方法会被执行。委托分三类:命名委托,多播委托,匿名委托,命名委托最为常用。
命名委托:
声明委托 修饰符 delegate 返回类型 委托名(参数列表);
实例委托:委托名 委托对象名=new 委托名(类名.方法名) 当被委托的方法是静态方法时,调用本类的静态方法不用加类名
委托名 委托对象名=new 委托名(new 类名().方法名) 实例方法
调用实例:委托名对象名(参数);
多播委托:
委托的声明,实例,调用和命名委托一样,多播委托可以通过+=和-=添加和撤销方法。
委托对象名+=对象.方法;
委托对象名-=对象.方法;
匿名委托:
委托声明:修饰符 delegate 返回类型 委托名(参数列表);
委托实例:委托名 委托对象名=delegate {代码块};//记得加在{}后加分号
委托调用:委托对象名(参数);
为什么要用委托:我们可以动态的调用所需的方法,这是我在看别人的项目时候感悟的。
class Program
{
public delegate void Delegate();
static Dictionary<string,Delegate> diction=new Dictionary<string,Delegate>();
static public void A()
{
Console.WriteLine("A");
}
static public void B()
{
Console.WriteLine("B");
}
static public void C()
{
Console.WriteLine("C");
}
static void Main(string[] args)
{
diction.Add("A", A);
diction.Add("B", B);
diction.Add("C", C);
String str = Console.ReadLine();
diction[str]();
}
}
3.事件
事件是一中引用类型,是特殊的委托。
事件的使用方法:
定义委托:
修饰符 delegate 返回类型 委托名(参数);
事件定义:
修饰符 event 委托名 事件名;
实例化事件:
对象.事件名=new 委托名(处理方法);
调用触发事件
public delegate void Delegate();//定义委托
public static event Delegate writeEvent;//定义事件名
static public void A()//定义委托中调用的方法即事件的处理方法
{
Console.WriteLine("A");
}
static void Do()//触发事件
{
writeEvent();//必须和事件名一样
}
static void Main(string[] args)
{
writeEvent = new Delegate(A);//添加方法
Do();//调用触发事件
}
4.异常
编程错误:编译错误,逻辑错误,编译错误在VS页面会被标红色波浪下划线,程序无法运行。
异常:运行时异常,在运行过程中的错误,比如说除数为零,将类似“ABC”的字符串转为整数。
搜友异常派生于Exception,异常又分为系统异常(SystemException)和应用异常(ApplicationException);
C#中异常处理的三种形式:
try{}catch(){} ,try{}fianlly{} ,try{}catch()finally{}
try:有异常时,抛出异常
catch:处理异常,可以有多个catch,多个catch相当于多分支if语句,只会执行其中一个。
finally:无论是否抛出异常都会执行fially中的语句块。
4.线程
1.Thread:主要用于创建线程,线程的执行,中断,阻塞,挂起。
2.TheadStart:用于创建委托的实例,实例委托的方法必须无参和无返回值,再用委托实例实例Thread线程。
ThreadStart ts=new ThreadStart(方法名);//委托线程要调用的方法
Thread td=new Thread(ts);//创建线程
td.Start();//开启线程
- ParameterizedThreadStart :用于创建委托的实例,委托方法方法必须没有返回值而且参数是Object,参数只能有一个,不是Object的派生类,就是Object本类。
ParameterizedThread pd=new ParameterizedThread(方法名);
Thread td=new Threa(pd);
td.Start(参数);
4.Priority:线程优先级
线程的优先级通过Thred.Priortity设置,默认属性是normal;优先级的值是枚举类型ThredPriority中的Lowest, BelowNormal, Normal, AboveNormal, Hightst, 优先等级高的执行机会多余优先级低的,不是说先执行完高的在执行优先级低的。
5.Thread的isBackground属性:默认的是false,即该线程不是后台线程,设置为ture的话是后台线程。
后台线程:程序不会考虑后台线程是否执行完毕直接退出程序。
前台线程:程序会等待所有前台线程执行完毕在退出。
public static void TextA(Object str)
{
for(int i=0;i<1000;i++)
Console.WriteLine("A :"+i);
}
public static void TextB(Object str)
{
for (int i = 0; i < 10; i++)
Console.WriteLine("B :"+i);
}
static void Main(string[] args)
{
string str = "123"
; ParameterizedThreadStart ts = new ParameterizedThreadStart(TextA);
Thread td = new Thread(ts);
td.IsBackground = true;
td.Start(str);
ParameterizedThreadStart tsB = new ParameterizedThreadStart(TextB);
Thread tdB = new Thread(tsB);
tdB.Start(str);
}
运行结果
A :0
B :0
B :1
B :2
B :3
B :4
B :5
B :6
B :7
B :8
B :9
A :1
A :2
A :3
A :4
A :5
A :6
A :7
A :8
A :9
A :10
A :11
A :12
A :13
A :14
A :15
6.lock:锁,锁保证了被加锁的代码块只有获得了锁才能执行,一次只能有一个程序块获得锁,只有锁内的代码块执行玩,才会继续执行其他线程。
lock(object)
{
//代码块
}
private static Program pr=new Program();
public static void TextA(Object str)
{
lock(pr)
for(int i=0;i<25;i++)
Console.WriteLine("A :"+i);
}
public static void TextB(Object str)
{
lock(pr)
{
for (int i = 0; i < 25; i++)
Console.WriteLine("B :" + i);
}
}
static void Main(string[] args)
{
string str = "123"
; ParameterizedThreadStart ts = new ParameterizedThreadStart(TextA);
Thread td = new Thread(ts);
td.IsBackground = true;
td.Start(str);
ParameterizedThreadStart tsB = new ParameterizedThreadStart(TextB);
Thread tdB = new Thread(tsB);
tdB.Start(str);
}
运行结果
A :0
A :1
A :2
A :3
A :4
A :5
A :6
A :7
A :8
A :9
A :10
A :11
A :12
A :13
A :14
A :15
A :16
A :17
A :18
A :19
A :20
A :21
A :22
A :23
A :24
B :0
B :1
B :2
B :3
B :4
B :5
B :6
B :7
B :8
B :9
B :10
B :11
B :12
B :13
B :14
B :15
B :16
B :17
B :18
B :19
B :20
B :21
B :22
B :23
B :24
7.Monitor:锁,Monitor可以添加等待获得锁的时间,这样就会避免死锁。
Monitor.TryEnter(object,s毫秒);
s毫秒后结束线程。
用法:
Monitor.TryEnter(object);
try{
//代码块
}finally
{
Monitor.Exit(object);
}
8.Mutex:用于线程同步,当多个线程同时访问一个资源时,保证一次只有一个线程访问一个资源。
Mutex类的WaitOne()等待资源被释放返回bool类型值,ReleaseMutex()用于释放资源。
public static Mutex mutex = new Mutex();
public static void Out(Object i)
{
if(mutex.WaitOne())//判断资源是否释放
{
try
{
Console.WriteLine("你是老几{0}。", i);
}
finally
{
Console.WriteLine("老几{0},你走了。", i);
mutex.ReleaseMutex();
}
}
}
static void Main(string[] args)
{
ParameterizedThreadStart ps = new ParameterizedThreadStart(Out);
Thread td = new Thread(ps);
td.Start(1);
Thread td1 = new Thread(ps);
td1.Start(2);
}
运行结果:
你是老几2。
老几2,你走了。
你是老几1。
老几1,你走了。