zoukankan      html  css  js  c++  java
  • C#学习之Timothy Liu

    原文出自 

    本文摘录了一些值得学习的地方。

    1.对一个程序来说,静态指编辑期、编译期,动态指运行期。 
    静态时装在硬盘里,动态时装在内存里。

    2.反射示例 

    通过反射获得类的属性和方法。

    static void Main(string[] args)
    {
        Type myType = typeof(Form);
        Console.WriteLine(myType.BaseType.FullName + Environment.NewLine + myType.FullName);
        var pInfos = myType.GetProperties();
        foreach (var p in pInfos)
        {
            Console.WriteLine(p.Name);
        }
        var mInfos = myType.GetMethods();
        foreach (var m in mInfos)
        {
            Console.WriteLine(m.Name);
        }
    }

    3.Stack Overflow 栈的溢出

    3.1.函数调用过多(算法错误) 下面的不良递归

    public void BadMethod()
    {
    
    int x=100;
    BadMethod();
    
    }

    3.2.栈上分配了过多的内存  unsafe为不安全的代码 

     unsafe
    {
    int *p=stackalloc int [9999999];
    }

    4.C#语言类型系统

    1. C# 类型分为引用类型和值类型

    1. 引用类型包括类、接口、委托,值类型包括结构体和枚举

    1. 所有类型都以 Object 为自己的基类型

    5.方法永远都是类的成员

    C# namespace中不能有方法。

    6.构造器

    构造函数译为构造器,成员函数译为方法,本质都是函数。

     以上的方法也可以初始化,但是成员变量需要公有。

    初始化构造器一般选择构造方法实现。

    7.重载

    方法签名:方法名称 + 类型形参的个数 + 每个形参(从左往右)的类型和种类(值、引用或输出)。方法签名不包含返回类型。

    重载:方法名相同,参数个数、次序、类型不同。 

    重载对返回值没有要求。

    如果参数的个数、类型、次序都相同,方法名也相同,仅返回值不同,则无法构成重载。

     哪怕次序不同都是重载。与返回类型无关。

    8.字段和属性

    字段就是与对象或类型相关联的变量。

    属性是用于访问对象或类型的特征的成员,是字段的自然扩展。

    建议:永远使用属性(而不是字段)来暴露数据,即字段永远是 private 或 protected 的。 
    字段只在类内部使用,类之间交换数据,永远只用属性。

    9.委托与事件

    委托是类,声明的位置和class同一个级别。委托却和一般类的声明不同,是为了照顾可读性和C/C++传统。

    委托的一般使用:把方法当做参数传给另一个方法。

    事件和委托的关系类似于字段和属性,事件是委托的包装器。

    我:委托的使用层次还是比较高的,以后真的需要用的时候还是需要好好的研究。

    10.多态和重写

    多态是基于重写的

    1.继承:向子类中添加父类没有的成员,子类对父类的横向扩展

    2.重写:纵向扩展,成员没有增加,但成员的版本增加了

    Override重写

    子类对父类成员的重写。

    只有对子类可见的父类成员可以重写,具体说就是 protected 和 public。例如子类能继承父类 private 的成员,但无法访问,即不可见、不可重写。

    重写需要父类成员标记为 virtual,子类成员标记 override

    Hide (此情况了解即可,原则不会用到Hide)

    如果子类和父类中函数成员签名相同,但又没标记 virtual 和 override,称为 hide 隐藏

    class Program
    {
        static void Main(string[] args)
        {
            Vehicle v = new Car();
            v.Run();
        }
    }
    
    class Vehicle
    {
        public void Run()
        {
            Console.WriteLine("I'm running!");
        }
    }
    
    class Car : Vehicle
    {
        public void Run()
        {
            Console.WriteLine("Car is running!");
        }
    }

    这会导致 Car 类里面有两个 Run 方法,一个是从 Vehicle 继承的 base.Run(),一个是自己声明的 this.Run()。

    可以理解为 v 作为 Vehicle 类型,它本来应该顺着继承链往下(一直到 Car)找 Run 的具体实现,但由于 Car 没有 Override,所以它找不下去,只能调用 Vehicle 里面的 Run。

    11.抽象类与开闭原则

    引言

    接口和抽象类是现代面向对象的基石,也是高阶面向对象程序设计的起点。

    学习设计模式的前提:

    1.透彻理解并熟练使用接口和抽象类

    2.深入理解 SOLID 设计原则,并在日常工作中自觉得使用它们

    要做到这两点,你必须在一个有质量文化的团队中,踏踏实实的写两三年代码。
    建议尽快离开没有质量文化的组,在这些地方你即难学到好东西还会养成一身坏毛病。

    算法、设计原则、设计模式必须要用到工作中去,才能真正掌握。
    还是那句话“学习编程的重点不是学是用”。

    SOLID(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转

    抽象类

    abstract 成员即暂未实现的成员,因为它必须在子类中被实现,所以抽象类不能是 private 的。

    抽象类不可以实例化。

    一个类不允许实例化,它就只剩两个用处了:

    1.作为基类,在派生类里面实现基类中的 abstract 成员

    2.声明基类(抽象类)类型变量去引用子类(已实现基类中的 abstract 成员)类型的实例,这又称为多态

    抽象方法的实现,看起来和 override 重写 virtual 方法有些类似,所以抽象方法在某些编程语言(如 C++)中又被称为“纯虚方法”。

    virtual(虚方法)还是有方法体的,只不过是等着被子类重写 abstract(纯虚方法)却连方法体都没有。

    纯抽象类版(接口)

    abstract 中的抽象方法只规定了不能是 private 的,抽象方法还可以是 protected 和 internal,而接口中的“抽象方法”只能是 public 的。

    这样的成员访问级别就决定了接口的本质:接口是服务消费者和服务提供者之间的契约。

    耦合与内聚

    通俗的讲:耦合就是类之间的联系即块间联系,内聚就是类之内的联系即块内联系。

     显示接口实现,这个功能挺有意思的。目前还不知道怎么去用 以下放个例子。

    class Program
    {
        static void Main(string[] args)
        {
            var wk = new WarmKiller();
            wk.Love();
            wk.Kill();
        }
    }
    
    interface IGentleman
    {
        void Love();
    }
    
    interface IKiller
    {
        void Kill();
    }
    
    class WarmKiller : IGentleman, IKiller
    {
        public void Love()
        {
            Console.WriteLine("I will love you forever ...");
        }
    
        public void Kill()
        {
            Console.WriteLine("Let me kill the enemy ...");
        }
    }
    
    
    显示实现:
    static void Main(string[] args)
    {
        IKiller killer = new WarmKiller();
        killer.Kill();
    
        var wk = (WarmKiller) killer;
        wk.Love();
    }
    ...
    class WarmKiller : IGentleman, IKiller
    {
        public void Love()
        {
            Console.WriteLine("I will love you forever ...");
        }
    
        // 显示实现,只有当该类型(WarmKiller)实例被 IKiller 类型变量引用时该方法才能被调用
        void IKiller.Kill()
        {
            Console.WriteLine("Let me kill the enemy ...");
        }
    }
    显示实现

    反射

    反射:你给我一个对象,我能在不用 new 操作符也不知道该对象的静态类型的情况下,我能给你创建出一个同类型的对象,还能访问该对象的各个成员。

    C# 和 Java 这种托管类型的语言和 C、C++ 这些原生类型的语言区别之一就是反射。

    依赖注入的理解可以参考

    12.泛型

    泛型在面向对象中的地位与接口相当。其内容很多,今天只介绍最常用最重要的部分。

    泛型委托和泛型接口。

    class Program
    {
        static void Main(string[] args)
        {
            //var stu = new Student<int>();
            //stu.Id = 101;
            //stu.Name = "Timothy";
    
            var stu = new Student<ulong>();
            stu.Id = 1000000000000001;
            stu.Name = "Timothy";
    
            var stu2 = new Student();
            stu2.Id = 100000000001;
            stu2.Name = "Elizabeth";
        }
    }
    
    interface IUnique<T>
    {
        T Id { get; set; }
    }
    
    // 泛型类实现泛型接口
    class Student<T> : IUnique<T>
    {
        public T Id { get; set; }
    
        public string Name { get; set; }
    }
    
    // 具体类实现特化化后的泛型接口
    class Student : IUnique<ulong>
    {
        public ulong Id { get; set; }
    
        public string Name { get; set; }
    }
    泛型接口

    Action和Func泛型委托

    static void Main(string[] args)
    {
        Action<string> a1 = Say;
        a1("Timothy");
    
        Action<int> a2 = Mul;
        a2(1);
    }
    
    static void Say(string str)
    {
        Console.WriteLine($"Hello, {str}!");
    }
    
    static void Mul(int x)
    {
        Console.WriteLine(x * 100);
    }
    Action泛型委托
    static void Main(string[] args)
    {
        Func<int, int, int> f1 = Add;
        Console.WriteLine(f1(1, 2));
    
        Func<double, double, double> f2 = Add;
        Console.WriteLine(f2(1.1, 2.2));
    }
    
    static int Add(int a, int b)
    {
        return a + b;
    }
    
    static double Add(double a, double b)
    {
        return a + b;
    }
    Func泛型委托
  • 相关阅读:
    RSA使用
    C#获取主机信息
    NSIS打包软件使用
    C#获取局域网主机
    C#实现Web链接启动应用程序
    4.布局介绍
    Server Sql 多表查询、子查询和分页
    C# File类常用方法
    Vue 使用技巧手记
    前端面试题手记
  • 原文地址:https://www.cnblogs.com/cdjbolg/p/11962913.html
Copyright © 2011-2022 走看看