C#中的一些基本方式总结

目录

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.迪米特法则(一个模块或对象应尽量少的与其他实体之间发生相互作用)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值