C#高级笔记
monitor 加锁解锁
lock
线程执行带参数的方法
PraameterizedThreadStart 带参数的
ParameterizedThreadStart pts = new ParameterizedthreadStart(AddTest)
Thread t = new Thread(pts);
t.Start();
Invoke
标注[注解]:
Attribute属性(容易和类的属性Property混淆)、标记、特性、注解等。
Attribute用来对类、属性、方法等标注额外的信息,相当于贴一个标签。
DisplayName:
[Serializable]允许序列化
反射:
目的,动态的调用方法,动态的使用对象。
GAC,全局程序集缓存。公用的Assembly放到GAC中。
Assembly类是对程序集的描述(*)
AppDomain.CurrentDomain.GetAssemblise();获取程序的所有程序集
string fileName=@"";
Assembly asm = Assembly.LoadFile(fileName);
Type[] types = asm.GetTypes();
foreach(Type type in types){
Console.WriteLine(Type);
PropertyInfo[] pros =type.GetProperties();
foreach(PropertyInfo prop in pros){
Console.WriteLine(prop);
}
}
Type类(*):
Type类可以叫做“类的类”,一个类型对应一个Type类的对象,通过Type对象可以获得类的所有的定义信息,比如类都有哪些属性、哪些方法等。Type就是对类的描述
Type对象的方法,
typeof、GetType、GetExportedTypes(获得Assembly中定义的所有public类型)、GetTypes(获得Assembly中定义的所有internal类型)、GetType(Name)获得定义全名为name的类型信息。
//没有对象的时候通多类来获得类的描述
Type t1 = typeof(Dog);
object d1 = new Dog();
//.GetType()获得对象的类型的类型描述
Type t2 = d1.GetType();
Console.WriteLine(t2);
Type类的方法:
Activator.CreateInstance(Type t)会动态调用类的public无参构造函数创建一个对象,返回值就是创建的对象,如果类没有无参构造函数就会报错。
IsAssignableFrom(Type c)判断当前的类型变量是不是可以接受C类型变量的赋值。
A.IsAssignableFrom(B)//A类型的变量是否能从B类型的变量赋值
IsInstanceOfType(object o)//判断对象o是否是当前类的实例
IsSubclassOf//只适用于类,判断A是B的子类
反射调用成员:程序练习
利用反射可以调用私有的方法。
Person p = new Person();
Type type=p.GetType();
MethodInfo method = type.GetMethod("SayHello",BindingFlags.NonPublic);
method.Invoke(p,null);
反射案例-编辑器插件
//Plugin:插件. Addin:插件。
可以把文本全部大写、全部小写,动态扩展的编辑器工具
作业:1.日志框架 2.XML序列化器:把一个对象写成XML节点格式
泛型:
ArrayList
List
自己写泛型类:
public class DataContainer <T>
{
public T Data{get;set;}
}
public class MyKeyValue<Tkey,Tvalue>
{
public Tkey Key{get;set;}
public Tvalue Value{get;set;}
}
自己写泛型方法:
static T1 Hello<T1,T2>(T1 t1,T2 t2){}
泛型委托:
delegate void MyDelegate<T1,T2>(T1 t1, T2 t2);
MyDelegate<string,int> md=Hello;
static void Hello(string ,int){}
.net内置了一个Func委托
Func
static int Hello(){return 0;}
泛型的约束:
//约束T必须有无参的构造函数,约束对于泛型委托、泛型类都是一样的
static List
泛型约束之继承:
class PersonList
public void Dot(T t){}//约定了Person类,可以调用他的属性
}
class Person {}
class Chinese:Person{}
PersonList
int? 表示可空,编译器最终会翻译成Nullable
LazyObject(微软的强大之处,很贴心)
对象什么时候用,什么时候被创建,不占内存。
Lazy
person.Value.Hello();//Lazy的Value用获得延迟创建对象
自己的Lazy:
class MyLazy
private instance;
public T value(){
get{if(instance ==null){
instance =new T();}
return instance;}
} } }
代码管理:
VSS:
单例模式(解决多线程问题,没有并发):
只有一个对象的类
1.建立私有的构造函数 private Earth(){}
2.声明私有的静态成员 private static Earth instance =new Earth();
3.编写一个公共的静态方法,返回唯一的实例 public static Earth GetEarth(){return instance;};
序列化和反序列化:
类前需要标注:【Serializable】对象的属性、字段的类型也必须序列化
BinaryFormatter bf = new BinaryFormatter();
using (Stream stream = File.OpenWrite(@"C:\a.txt"))
{
bf.Serialize(stream,list);//序列化,把集合序列化到流中。
}
BinaryFormatter bf = new BinaryFormatter();
using (Stream stream = File.OpenRead(@"C:\a.txt"))
{
var list = bf.DeSerialize(stream).Tolist();//反序列化
}
文件流(高级):
Flush、强制把缓冲区中的数据写入文件
Close、会把没有写入缓冲区的数据写入文件再关闭
Dispose、方法会调用close,所以以后 用Stream的时候用using最保险
File.OpenRead ;File.OpenWrite;简写,不用new了。
GZIPStream压缩流(类似装饰者模式)
MemoryStream内存流,支持指针的前进后退,Seek()
StreamReader;StreamWriter;文本流
WebClient的流操作;
文件流(核心):
拷贝文件有两种方式:
1.将源文件内容全部读取到内存中,再写到目标文件中;一次性读写 dataset(处理小数据可以)
2.流的操作。读一点,写一点。像从一个缸里舀水到另一个缸里 sqldatareader
缓冲区 byte[] bytes = new bytes[102410245];
byte加密工具:
在缓冲区做处理:
byte.MaxValue-实际值;//byte的最大值减去实际值
进度条:progressbar设置它的value的最大值即可。
IO:
文件编码:将字符串以什么样的形式保存为二进制。ANSI,Unicode,UTF-8,
File类的常用静态方法:
- AppendAllText(string path,string contents),将文本contents附加到文件path中
- Exist(string path)判断文件path是否存在
- 默认采用UTF8编码
- ReadAllLines(string path)读取文本文件到字符串数组中
- ReadAllText(string path)读取文本文件到字符串中
- WriteAllText(string path,string contents)将文本contents保存到文件path中,会覆盖旧内容
- WriteAllLines(string path,string[] contents)将字符串数组逐行保存到文件path中,会覆盖旧内容
- Directory类的常用静态方法:
- Delete,Exists,GetDirectories(反射会用到),GetFiles,CreateDirectory,
- Path类的常用静态方法:
- ChangeExtension,修改文件的后缀(仅仅是把文件名当成字符串来处理,不会对文件修改,也不管文件存不存在)
- Combine,将两个路径合到一起
- GetDirectoryName,得到文件的路径名
- GetExtension,判断文件的后缀名
- GetFullPath,得到文件的全路径。 .\当前路径, ..\上一级路径
- 得到当前exe所在的路径
- Assembly.GetExecutingAssembly().Location;
设计模式:
共有多少种设计模式?就一种,多态!
设计模式就是多态!!!
开闭原则:对变化开放,对修改关闭
多态:
interface接口
abstract抽象类
: ,virtual override继承
接口和抽象类在使用方面最主要的区别:接口提供公共的行为(能干什么),抽象类提供公共的实现(怎么干)。
例子:
设计模式:通过接口访问不同数据库——配置提供者(SettingsProvider):可通过配置选用不同数据库
ISettingProvider接口,TextSettingProvider类,SqlSettingProvider类,AccessSettingProvider类。
模板方法模式:给接口实现一层抽象类,把接口的方法实现,就像一层模板。
在ISettingProvider接口的基础上,实现BaseDbSettingProvider抽象类。
装饰者模式:在抽象类的基础上装饰一层加密,把数据进行装饰。
在BaseDbSettingProvider抽象类的基础上,实现DESSettingProvider类进行装饰。
CTS(Common Type System)
CLR(Common Language Runtime)
浅拷贝和深层拷贝:
浅层拷贝:就是只拷贝类的第一层成员,而且如果成员是引用类型,则引用同一份。
深层拷贝:把对象引用的所有直接、间接的对象都拷贝一份。完全的拷贝一份。
实现接口:ICloneable
public object Clone(){
//方法内容需要自己写
//若仅仅是浅层拷贝
this.MemberwiseClone();//返object类型,是protected方法
}
指针:
1.项目允许不安全代码
2.方法或者代码块标记为unsafe
int i =5;
int* ip = &i;
*ip=6;
Console.WriteLine(i);
结构体(Struct):
回忆之前的类型有:enum delegate class
结构体是值类型,拷贝一份
性能较高,与int bool 等类型的基类都是ValueType
字符串拘留池(CLR:)
因为字符串是不可变的,所以CLR可能会将相同值的字符串用同一个实例。程序中大量使用字符串,有不少是重复性的,为了降低内存占用,.Net将代码中声明的字符串放到字符串拘留池中,值相同的字符串共享同一个实例。
如:
object.ReferenceEquals(s1,s2);//判断是否是同一个对象
string s1="abc";string s2="abc";string s2="a"+"bc";//编译器优化
object.ReferenceEquals(s1,s2);//判断为True,是同一个对象,这就是CLR的工作
StringBuilder:
大量的字符串相连会产生大量的中间字符串,字符串是对象,对象的产生是满的,而且会占用大量的内存。
IDisposable接口:
GC只能回收GC托管内存资源,对于数据库连接、文件句柄、Socket连接等资源就无能为力。
实现了IDisposable接口,在Dispose方法中进行回收。
如:
FileStream f s= new FileStream();
try{
fs.Read()}
finally{
fs.Dispose();}
using 会自动调用Dispose方法进行销毁。
程序调优:
CLRProfiler(免费)微软自己的。
.Net.Memory.Profiler (付费)第三方。分析对象的创建、回收,内存泄露的原因。
WinDbg(*)成为牛人必备的工具。
GC垃圾回收机制(Garbage Collection):
没有引用了才有可能被回收,若正在引用着是绝对不能被回收的。
频繁的GC会造成系统性能下降,不是有了垃圾就清理。
GC就像清洁工,有了垃圾就去清扫,累死他了。
GC.Collect();强制立即回收
WeakReference 弱引用:监控
WeakReference wr = new WeakReference(p1);
wr.IsAlive//判断指向的对象还活着吗?
程序集(C#):
可以看做把一堆相关类打成一个包
目的:程序中只引用必须的程序集,减小程序的尺寸;一些程序集内部的类不想让其他程序集调用。
exe、dll都是程序集,只不过exe有入口而已,exe也可以被添加引用。dll不一定是程序集(VC写的dll就不是程序集),程序集不一定是dll
*委托和事件的区别:
委托:指向函数的变量,无法把函数串起来,存在多个函数时,指向最后的函数
事件:
委托和事件没有可比性,因为委托是类型,事件是对象;事件的内部使用委托实现的,对于事件来讲,外部只能“注册自己+=、注销自己-=”,外界不可以注销其他的注册者,外界不可以主动触发事件,因此如果用Delegate就没法进行上面的控制,因此诞生了事件这种语法。(add、remove),事件是用来阉割委托实例的。事件只能add、remove自己,不能赋值。
*匿名函数(多线程的时候常用):
FilterDelegate fd = delegate(string s){ Console.WriteLine("{0表达式}",s)};
fd("lambda");
*lambda表达式:
(参数列表)=>{方法体 };
FilterDelegate fd = (s) =>{ Console.WriteLine("{0表达式}",s)};
fd("lambda");
public delegate void FilterDelegate();
SharePoint CMS MOSS(Microsoft Office SharePoint Server)
扩展方法:
1.声明为静态类(static class)
2.在静态方法的第一个参数上加this(this string str)
结果 ,string str =“abc”; str.方法().方法().方法();
非扩展方法: 方法(方法(方法(方法(str))))
可根据返回类型继续点出扩展方法。
linq(最后都会编译成委托):
需引用 using System.linq;
IEnumerable静态类,里面包含.Where(i=>i) .Select .Orderby 等等
linq to sql(编译时会) :
var list = from i in values //foreach(int i in values) 遍历集合中的每个元素
where i >10
orderby i descending
select "["+i+"}"; //select 什么类型 返回就是什么类型 select new {}(匿名类型) //select new Person { Name="";Age=};
var list = from str in values
let n =Convert.ToInt32(str)//声明临时变量n
where n>100
select n;
foreach(int i in list){
Console.WriteLine(i);;
}
//将Dictionary中年龄大于20的人的姓名用“,”分割打印出来
Dictionary <string ,int > dict =new Dictionary<string,int>();
dict["tom"]=20;
dict["ainy"]=30;
dict["bulusi"]=120;
dict["tony"]=2;
var list =from str in dict.Keys
where dict[str]>20
select str;
Console.WriteLine(string.Join(",",list.ToArray()));
//取出现次数最多的三个数
int[] values = { 1, 2, 3, 4, 5, 6, 2, 3, 4, 5, 4, 5 };
var result = from item in values
group item by item into g
orderby g.Count() descending
select new { 数字 = g.Key, 次数 = g.Count() };
foreach (var item in result.Take(3))
{
Console.WriteLine(item.数字 + "=" + item.次数);
}
Console.ReadKey();
linq常用扩展:
下面的方法都是IEnumerable
- Average计算平均值; Min最小元素;Max最大元素;Sum元素总和; Count元素数量;
- Concat连接两个序列;//Unoin all
- Contains序列是否包含指定元素;
- Distinct取得序列中的非重复元素;
- Except获得两个序列的差集;
- Intersect获得两个序列的交集;
- First取得序列第一个元素;
- Single取得序列的唯一一个元素,如果元素个数不是1个,则报错;!!!严谨的程序。
- FirstOrDefault 取得序列第一个元素,如果没有一个元素,则返回默认值;
- Linq只能用于泛型的序列,IEnumerable
,对于非范型,可以用Cast或者OfType - IEnumerable的方法:
- Cast
:由于Linq要针对范型类型操作,对于老版本.Net类等非范型的IEnumerable序列可以用Cast方法转换为范型的序列。ArrayList l; IEnumerable il = l.Cast (); - OfType
:Cast会尝试将序列中所有元素都转换为TResult类型,如果待转换的非范型序列中含有其他类型,则会报错。OfType则是只将序列中挑出指定类型的元素转换到范型序列中。 - Linq的效率怎么样(小数据量、对性能要求不高的环节用linq很方便,而且延迟加载机制降低了内存占用,比一般人写的程序效率都高)
Cast用来将非泛型的集合转换成泛型的集合
如:
object[] values ={12,23,3,2,3,4,43,};
Console.WriteLine(values.Cast<int>.Mix());
OfType仅仅把指定类型的元素转成泛型集合
object[] values ={12,23,3,2,3,4,43,"我是米老鼠"};
Console.WriteLine(values.OfType<int>.Mix());

浙公网安备 33010602011771号