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泛型委托
  • 相关阅读:
    通过HttpListener实现简单的Http服务
    WCF心跳判断服务端及客户端是否掉线并实现重连接
    NHibernate初学六之关联多对多关系
    NHibernate初学五之关联一对多关系
    EXTJS 4.2 资料 跨域的问题
    EXTJS 4.2 资料 控件之Grid 那些事
    EXTJS 3.0 资料 控件之 GridPanel属性与方法大全
    EXTJS 3.0 资料 控件之 Toolbar 两行的用法
    EXTJS 3.0 资料 控件之 combo 用法
    EXTJS 4.2 资料 控件之 Store 用法
  • 原文地址:https://www.cnblogs.com/cdjbolg/p/11962913.html
Copyright © 2011-2022 走看看