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 f =Hello;
static int Hello(){return 0;}
泛型的约束:
//约束T必须有无参的构造函数,约束对于泛型委托、泛型类都是一样的
static List CreatList(int n) where T:new(){}
泛型约束之继承:
class PersonList where T:Person{
public void Dot(T t){}//约定了Person类,可以调用他的属性
}
class Person {}
class Chinese:Person{}
PersonList list = new PersonList();
int? 表示可空,编译器最终会翻译成Nullable类型
LazyObject(微软的强大之处,很贴心)
对象什么时候用,什么时候被创建,不占内存。
Lazy person =new Lazy();
person.Value.Hello();//Lazy的Value用获得延迟创建对象
自己的Lazy:
class MyLazy where T:new(){
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());
posted @ 2022-04-05 20:45  小堂子  阅读(70)  评论(0)    收藏  举报