目录
1.委托delegate---c#中的将方法作为参数传递
2.堆和栈
3.override重写
4.new关键字,如果子类声明了和父类同样的方法,但用new声明了,会隐藏掉父类的方法。
5this和base
6.sealed类
7.泛型方法
8.泛型类型约束
9特性
10.开启线程
11.socket服务端
12 设计原则
1.委托delegate---c#中的将方法作为参数传递
1.自定义委托
//1、声明委托类型
public delegate void SumDelegate(int a, int b);
//2、有一个方法包含了执行的代码
public static void Sum1(int a, int b)
{
Console.WriteLine(a + b);
}
static void Main(string[] args)
{
//3、创建委托实例,使用了new 关键字,说明委托也是类,将方法名Add作为参数绑定到该委托实例
var sum = new SumDelegate(Sum1);
//4、调用委托实例
sum(1, 2);
}
// 3匿名方法调用
static void Main(string[] args)
{
SumDelegate sum = delegate(int a, int b) { Console.WriteLine(a + b); };
sum(1,2);
}
2.内置的无返回值委托
void b(int i)
Action<int,int> a=b;// 系统字定义的委托类型,方法为b ,参数为int ,int ,没有返回值
b(i)
3.内置的右返回值得委托
Func<string,int> a =b // 系统字定义的委托类型,方法为b ,参数为string ,返回值为int
Func<int,int> plus=delegate(int a,int b)
{return a+b;}
或者
Func<int,int> plus=(a,b)=>{return a+b;}
4.多播委托
Action a=Test1;
a+=c;// 新增一个委托
a-=Test1// 减少一个委托
调用委托变量会按照次序依次调用
遍历多播委托中的方法
Delegate[] c=a.GetInvocationList()
5.event事件订阅观察者模式
一个特殊的委托,本质上就是多播委托
public delegate void SumDelegate(int a, int b);
在类中声明事件,事件是对象的成员,new出来就行
public event SumDelegate attackevent;
2.堆和栈
堆空间大,但是速度慢
引用类型的数据
空间大,速度慢
C#中String类是内置的引用类型数据
指针会指向堆中的数据,本身结构是不规则排列的
栈
空间小,速度快
存放的数据是值类型(整数,bool,struct char 小数)和引用类型的引用
便于理解可以看做是保存着我们代码执行的步骤,当我们使用完一个就从栈顶去掉一个,因此本身是不需要我们清理的
3.override重写
主要用于在派生类中重写方法覆盖基类,
1.在基类中需要对同一方法进行virtual声明,如果在派生类中没有用override重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法
2.abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现基类为抽象类,方法也为抽象方法
4.new关键字,如果子类声明了和父类同样的方法,但用new声明了,会隐藏掉父类的方法。
public new void Move()//
5this和base
public Derive:base()// 子类构造函数
6.sealed类
允许类从基类继承,以及防止它们重写特定的虚方法或虚属性。
7.泛型方法
public static T GetSum<T,B>(T a,T b){
return a+""+b;}
GetSum<int,int>(23,12);GetSum<double,int>(23.2,12)
泛型类
class ClassA<T,A>{
private T a;
private A c;
}
8.泛型类型约束
where T : struct | T必须是一个结构类型
where T : class | T必须是一个Class类型
where T : new() | T必须要有一个无参构造函数
where T : NameOfBaseClass | T必须继承名为NameOfBaseClass的类
where T : NameOfInterface | T必须实现名为NameOfInterface的接口
public sealed partial class ZeneralDataAccess<T> where T : class
{}
9特性
[Obsolete("该方法已被弃用")]// 表示一个方法被弃用了
[Conditional(isTest)]//判断isTest是否被定义
[DebuggerStepThrough]//跳过断点
CallerFilePath 获取调用该方法的文件路径
CallerLineNumber 获取调用该方法的源文件的行号
CallerMemberName 获取调用该方法的方法名
static void Print(string str, [CallerFilePath]string file = "",
[CallerLineNumber]int line = 0, [CallerMemberName]string method = "")
{ }
自定义特性
1.使用【MyTest("此方法已注释")】会调用MyTestAttribute类的构造方法
如果想获取特性类的值,可以通过反射获取信息
10.开启线程
Task 类 (System.Threading.Tasks) | Microsoft Docs
1.异步开启线程
// 1.通过委托,开启一个线程
Func<int,string,int> a=Test
// 开启一个线程去执行a所引用的方法,倒数第二个参数表示回调函数,就是当线程结束的时候回调用这个委托指向的方法,
倒数第一个参数用来给回调函数传递数据,用回调不会阻碍主线程的调用,如果返回值写在主线程里,是会挂起主线程,直到子线程执行完毕。
IAsyncResult ar=a.BeginInvoke(100,'siki',OnCallBack,null)
// 判断当前线程是否已执行完毕
while(ar.IsCompleted==false)
//检测线程结束,1000毫秒表示超时时间,如果等待了1000毫秒线程还没结束,方法返回false,否则返回true
bool isEnd=ar.AsyncWaitHandle.WaitOne(1000);
// 获得异步线程的返回值
int res=a.EndInvoke(ar);
static void OnCallBack(IAsyncResult ar){
Func<int,string,int> a=ar.AsyncState as Func<int,string,int>;
int res=a.EndInvoke(ar);
}
// 使用lam表达式
a.BeginInvoke(100,"siki",ar=>{
int res=a.EndInvoke(ar);
},null)
2.Thread开启线程
Thread t=new Thread(方法)// 这个是前台线程
t.IsBackground=true;//设置为后台线程,如果前台进程结束,后台进程也结束了。如果后台进程结束,不会影响前台进程
t.Start("参数")
t.Abort();//终止这个线程的执行
t.Join();//当前线程睡眠,等待t线程执行完,然后继续运行下面的代码
3.线程池
线程池中的线程执行完指定的方法后并不会自动消除,而是以挂起状态返回线程池,
如果应用程序再次向线程池发出请求,那么处以挂起状态的线程就会被激活并执行任务,
而不会创建新线程,这就节约了很多开销。只有当线程数达到最大线程数量,
系统才会自动销毁线程。因此,使用线程池可以避免大量的创建和销毁的开支,具有更好的性能和稳定性。
线程池中的线程都是后台线程。
不能给入池的线程设置优先级或名称。
入池的线程只能用于时间较短的任务。如果线程要一直运行(比如Word的拼写检查线程),就应该使用Thread类创建一个线程
1.添加线程
ThreadPool.QueueUserWorkItem(new WaitCallback(方法名));
或
ThreadPool.QueueUserWorkItem(new WaitCallback(方法名), 参数);
2.ThreadPool.SetMaxThreads(workerThreads, portThreads);// 设置线程池中的线程方法
4.任务
任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制.在我的理解里,任务跟线程应该差不多,但是按照这个理解,应该也是有一个缓存队列来执行的(先保留疑点)
//第一种创建方式,直接实例化:必须手动去Start
var task1 = new Task(() =>
{
});
task1.Start();
//第二种创建方式,工厂创建,直接执行
var task2 = Task.Factory.StartNew(() =>
{
});
11.socket服务端
socket不是协议,是是位于应用层和传输控制层之间的一组接口,是为了实现tcp和udp特意分离的一组接口。
网络通信三要素
IP地址:网络上主机设备的唯一标识
端口号: 有效端口:0~65535,其中0~1024由系统使用,开发中一般使用1024以上端口.
传输协议:TCP,UDP
1.TCP(面向连接,提供可靠的服务)
2.udp(无连接,传输速度快)
TcpListener
UdpListener
NetworkStream
12 设计原则
1.单一职责原则
2.开闭原则(Open-Closed Principle)(接口)
3.里氏代替原则(指的是子类必须替换掉它们的父类型)
4.依赖倒置原则(面向接口编程,而不是面向实现编程)
5.接口隔离原则(使用多个专门的接口比使用单一的总接口要好)
6.合成复用原则
7.迪米特法则(一个模块或对象应尽量少的与其他实体之间发生相互作用)