编程技术专题

# C#.NET概述

# C#语言

编程语言是类似的,程序员的能力决定了程序的能力。

C#之父安德斯.海尔斯伯格。

C#语言是最主要的.NET Framework兼容语言,它是为了和.NET Framework一起使用而专门设计的。但是C#本身是一门语言,它只是用于生成面向.NET环境的代码,并不是.NET的一部分。换言之,C#编写的代码总是运行在.NET Framework中。而且,在很多时候,C#的特定功能依赖于.NET。比如,在C#中声明一个int类型,实际上是.NET中System.Int32类的一个实例。.NET Framework 支持的一些特性,C#并不支持;C#支持的一些特性,.NET Framework并不支持,例如运算符重载。

# .NET的核心技术

.NET程序的开发和运行必须在安装了.NET FRAMEWORK 环境的设备上进行。.NET最终目标是让用户在任何地方、任何时间、利用任何设备都能访问互联网。需要解决语言差异、平台差异、协议差异、数据差异来实现 Internet 数据共享和无缝集成。用户无需知道这些信息存放在何处,所有后台的复杂性是完全屏蔽的。

开发环境IDE:.NET程序集成开发环境 VisualStudio 2019/2022。

多语言集成:Microsoft 在 .NET 平台上提供多种语言 Visual C++、 C#、F#、Visual J# 和 Visual Basic。

FCL(Framework Class Library):FCL是一个全面的类库。它是生成.NET Framework 应用程序、组件和控件的基础。FCL由命名空间组成。每个命名空间都包含可在程序中应用的类、结构、委托和接口等。常见的命名空间有System、System.Windows等。

CLR(Common language runtime): CLR公共语言运行时(库)。整个核心技术的底层,号称大管家。有两个主要功能:a、从中间语言到二进制的编译器。b、垃圾回收器(GC),而C++的内存必须由程序员编码释放,没有垃圾自动回收机制。GC不设置时间帧,对内存垃圾的回收是不确定的。.NET的核心是其运行库执行环境,称为公共语言运行库(CLR)或 .NET运行库。

托管代码与非托管代码:通常将在CLR控制下运行的代码称为托管代码 (Managed Code),类似于Java的虚拟机机制。非托管代码指不在CLR控制下的运行的代码,由操作系统直接运行

.NET安全机制:.NET的安全机制是基于代码的安全性,而 Windows 仅提供基于角色的安全性。

C# 程序经过两次编译,第一次比较慢,第二次比较快;第一次编译.NET源代码经过编译器编译成为中间代码(MSIL),第二次编译中间代码(MSIL)经过CLR编译成为机器代码(二进制代码0和1)。

MSIL是将.NET代码转化为机器语言的一个 中间过程 。它是一种介于高级语言和基于 Intel 汇编语言的伪汇编语言。平台无关,独立于CPU指令集,IL比Java字节码作用还要大,它总是即时编译(称为JIT编译),这就解释了托管IL代码与执行本地机器代码具有一样快的速度的原因。

CTS(Common Type System):通用类型系统。描述了类型的定义及其行为方式,描述了和类型相关的所有内容。

CLS(Common Language Specfication):公共语言规范。作用:定义所有.NET语言都应该遵循的规则,从而实现不同的语言的互操作

.NetFramework

# C#.NET基础

# 需要了解的知识点

◆ using :引入底层类库(FCL中的东西)。

◆ 语句以";"结束,表示执行一个动作。

◆ 注释://单行/**/多行/***/文档注释。

◆ 程序的扩展名有3个字母有4个字母。比如:.htm和.html都是网页的文件格式。其中.htm文件名是为了满足DOS系统的需求。DOS系统只认的3个字母的扩展名哦。

◆ cd.. 返回上一级 ,cd\返回根目录 ,cd目录名称。ipconfig windows IP配置命令 ,dir查看目录。

◆ 转义字符 "\" 。

◆ 如果要输出文件路径,可以在文件路径的前面添加一个路径的符号"@",比如输出@"e:\yang\3ds.exe"文件路径。

◆ 常量:程序运行过程中,其值始终不变的量称为常量。一声明就的赋初始值,并且不可以改变。常量名一般都是大写的。

◆ 变量:在程序运行过程中,其值可以改变的量称为变量。临时存储数据,变量一定要明确指定。属于强类型的。变量名字母,数字,下划线,美元符号,且不能以数字开头。

◆ 内存:内存像旅馆,开辟内存空间如同开旅店房间一样,不同的数据类型占用不同的内存空间。

◆ 访问修饰符是界定类、方法、数据的访问权限。

◆ Main方法为主程序的入口。

◆ 英文是采用 ASCII 编码的,中文是采用 UNICODE 编码的。字符都有对应的 ASCII 码数值,比如A对应65。

# 基本数据类型、运算符、运算

◆ C#值类型包括:简单类型,枚举型enum,结构型struct

简单类型:整型、浮点、小数、布尔

整型:sbyte\byte\char\short\ushort\int\uint\long\ulong;

浮点:float(精度为7位)\double (精度为15-16位);

小数默认的是double类型的数据;

小数型:decimal(精度为28-29位);

布尔型:bool(只取2种值true或者false);

枚举型:枚举型将变量的值一一列举出来,变量的值值限于列举出来的值的范围内。默认情况下,第一个枚举常量的值为0,后面的依次递增1。枚举常量不是变量不能为他们赋值。在定义枚举时可以改变枚举元素的值。

枚举型和结构型的区别:枚举数据类型不可以在方法中声明,可以改善代码的可读性,并不是不可或缺的,枚举和结构体都是值类型。枚举型的各个枚举元素的数据类型是相同的,枚举数只能代表一个枚举元素的值,而结构型是若干个数据成员与数据操作的组合,且各个数据成员的数据类型可以是不同的。

◆ 两个整数相除的整数,有小数时结果为小数。

◆ 数据类型转换:强制转换和隐式转换,数据转换时可以按照数据长度增加的方向进行,以保证精度不降低。byte和short型数据参与运算时,必须先转换成int型。char型可以隐式转换成 ushort、int、uint、long、ulong、float、double或 decimal,但不存在其它类型转到char类型的隐式转换。数据类型转换的方法有:Parse.XXX()、Convert.ToXXX()。

◆ 算术运算符与表达式:+、-、*、/、%、++、--共七种。

◆ 赋值运算符与表达式:一般情况下是"变量=表达式",复合赋值运算符"+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>="。

◆ 关系运算符与表达式:==、!=、<、>、<=、>=。

◆ 逻辑运算符与表达式:!、&&(&)、||(|)、^。

◆ ++ ,--一元运算符的用法。只做自加操作时i++和++i没区别,当在参与到运算时,它们是有区别的,int i = 1; int n = i++;(先赋值后自加) 结果n = 1,i = 2。int i = 1;int n = ++i;(先自加后赋值)结果n = 2,i = 2。

◆ "+"在是数值的情况下,完成的是相加运算。在有字符串的情况下完成的是连接的作用。

◆ C#引用类型:类、接口、委托、数组、字符串、装箱和拆箱。

# 结构和控制语句

◆ 分支语句:if else的嵌套最好不要超过3层,多重if else适合做区间判断。switch 多分支语句, case 后面只能是int、string、bool 、char、枚举。default是可有可无的,所有的case都不满足的情况下才执行default。

◆ 循环语句:for语句、foreach语句、while语句、do / while 语句。

while----------循环适合于不确定循环次数的判断;

for-------------循环适合与确定循环次数的;

foreach-------遍历集合,是以只读的方式;

break----------关键字结束整个循环;

continue------关键字结束本次循环直接进入下次循环;

◆ return语句后面的语句不执行。

# 数组、集合、字符串

◆ 数组:是一种由若干个变量组成的集合,数组中包含的变量称为数组的元素,它们具有相同的类型。数组容纳的数据类型一定是相同的,数组中存放的数据是连续的优点是:读取速度快,查找速度快缺点是不能增容和出界。适用于个数确定的情况下。

◆ params:参数只能使用一次,其后面不能有其它任何的参数。

◆ 在开发中如果遇到多个数据的情况下,要考虑到数组和集合这两种数据类型。

◆ 装箱:是指数值类型转化为引用类型的过程,使得值类型和引用类型之间可以互相协作,是值类型和引用类型之间沟通的桥梁。装箱对的压力增大。装箱和拆箱会影响系统的性能。

◆ 拆箱:是指把引用类型转换为值类型的过程,拆箱对的压力增大。拆箱是以装箱为前提的。拆箱和装箱的数据类型必须保持一致。如果有继承关系可能发生装箱拆箱操作,如果无继承关系则肯定没有发生拆箱装箱操作。

◆ 字符串:直接赋值,内容不可变变量的值可以直接赋予。大量字符串的拼接会造成内存空间的浪费,所以应该避免字符串的多次拼接。每拼接一次就new一个对象出来。StringBuilder可以解决字符串大量拼接造成资源浪费的情况,StringBuilder是在原有字符串的基础上进行拼接的StringBuilder会自动增容,空间不够用的时候就自动增加空间

◆ 集合相关:Array是所有数组的基类,ArrayList(集合) 、Hashtable(集合) 、String 、StringBuilder、File(只能读取小文件)、Encoding、FileStream、StreamReader和StreamWriter。集合的长度问题,每次集合中实际包含的元素的个数(count)超过了可以包含的元素的个数(capacity)的时候,集合就会向内存中申请多开辟一倍的空间,来保证集合的长度一直够用。

# C#.NET面向对象

# 面向对象编程基础

◆ 面向对象让我们有一个宏观的思维,这种思想更加接近于人类的自然思维。就是把一个大问题分解成若干小问题,然后再对小问题进行逐个实现。

◆ 人类都是先认识具体的事物(对象),然后慢慢的归纳出这种事物的类。但是在编程领域中是先有类,再有对象的。

◆ 类:表示一种概念,是对象的抽象,它为属于同类的所有对象提供统一的抽象描述;只描述对象具备哪些数据和行为,一般不去描述数据的值,类是没有状态的。类是具有相同属性和服务的一组对象的集合。

◆ 对象:表示一个实体,是类的实例。对象中的数据是具有确定的值,所以对象都是具有状态的。世间万物皆对象。

◆ 接口:是一种特殊的数据类型,负责声明类的标准行为,可以实现软件设计的规范化和标准化

接口是一种规范,只要一个类继承了接口,该类就要实现该接口中的所有方法;

接口不能被实例化,不能创建对象;接口中可以有方法、属性和索引器,不能有字段和构造函数;

接口成员不能加访问修饰符,默认的就是public且不能修改;

接口中的成员不能有具体的实现,是光说不做的;

接口之间可以继承,且可以多继承;

接口的作用是规范实现类,扩展类的行为,实现方法回调。

索引器举例:

class MyClass
{
    private int[] arr = new int[10];

    // 定义索引器
    public int this[int index]
    {
        get
        {
            // 通过索引访问数组元素
            return arr[index];
        }
        set
        {
            // 通过索引设置数组元素
            arr[index] = value;
        }
    }
}
class Program
{
    static void Main()
    {
        MyClass obj = new MyClass();
        
        // 通过索引器设置值
        obj[0] = 10;
        obj[1] = 20;
        
        // 通过索引器获取值
        Console.WriteLine(obj[0]);  // 输出 10
        Console.WriteLine(obj[1]);  // 输出 20
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

◆ partial:关键字,修饰部分类,部分类中不能有相同的方法。

◆ sealed:关键字,修饰密封类,密封类是不能够被继承但是可以继承别的类。相当于 java 的 final。

◆ 修饰符:public 、protected 、private、internal 、protected internal。默认情况下是私有的访问权限。类的访问修饰符有public 和 internal,internal只能在同一个项目中使用。internal是类和类成员的访问修饰符,是基于程序集的。

◆ new: 关键字,生成对象,子类方法覆盖父类方法时标注new关键字(多态中的方法隐藏)。

◆ this: 关键字,代表对象本身。只能出现在类的内部,且出现在实例成员中。写索引器时也需要this,构造函数的相互调用也需要this。

◆ static:静态的东西是属于类的,不属于具体对象。静态类中只能包含静态成员。静态函数只能访问静态数据。对象共享静态成员。静态成员只有一份。静态数据常驻内存,在类首次加载时。直到程序结束,与对象是否销毁无关。静态成员可以表达中立特性。静态成员在没有对象前就可以调用。

◆ 命名空间:用来解决类重名的问题,可以看作类的文件夹。同一命名空间下的类不必使用using。

◆ :base()可以显式的调用父类的构造函数。

◆ 委托:就是C#提供的一种以托管机制调用方法的特殊数据类型。其作用诸如房屋租赁、求职等日常活动中的中介结构类似。

◆ 事件:又称消息表示向对象发出的服务请求。

◆ 方法:表示对象能完成的服务或执行的操作功能。

◆ 对象的生命周期:为了加强内存管理,.NET公共语言运行时会把值类型变量和引用类型变量放在不同的内存区域中管理。值类型变量用"栈"来管理,栈是一种按照"先进后出"方法存取的内存区域。方法调用时值类型变量自动获得内存,方法调用结束时,值类型变量所占的内存将自动释放。引用型变量使用"堆"来管理,堆是分配对象时所使用的内存区域。方法调用时,new创建了对象,即为该对象从堆中分配内存,方法调用结束时,对象所占内存不会自动从堆中释放,需要由公共语言运行时的垃圾回收器来回收。垃圾回收器没有预定的工作模式,其工作时间间隔不可预知,通常在计算机内存不足的时候才自动启动。

◆ 值与引用的类型

类型分类:CTS中定义了两种数据类型,值类型和引用类型;

值类型包括结构 struct 和枚举 enum;

引用类型包括 类、数组、接口、委托;

分类的原因是出于性能的考虑;

结构struct是与类相似的一种数值类型;

声明结构,struct 结构名称 { 成员同类 };与类不同之处:类声明的对象只有在new创建后才能使用;结构声明时就有值,在没有显式new的情况下就可以使用;结构中不能显式的声明无参构造函数。如果在结构中出现自动属性,属性如果在构造函数中赋值,则必须为字段也赋值,调用无参构造函数为隐式字段赋值;

结构放在栈中,类放在堆中;

常用于占空间小的数据;

值类型存放在栈中,变量中存放内容;

引用类型存放在堆中,引用中存放的是内容在内存中的地址。

◆ 一个对象的生命周期可以分为以下几个阶段:使用new运算符创建对象并要求获得内存;对象初始化,包括对象的数据成员的初始化(由构造函数完成);使用对象,包括访问对象的数据成员、调用对象的方法成员;对象释放前,释放对象所占的资源,如关闭磁盘文件、网络连接等(由析构函数完成);释放对象,回收内存(由垃圾回收器自动完成)。

◆ 字段:(C#中称呼),成员变量(Java C++称呼)。字段是用来存储数据的。字段的值代表某个对象的数据状态。不同的对象,数据状态不同,意味着各字段的值不同。字段是指在类或结构中声明的任何类型的"类级别"变量。

◆ 行为:属性、方法、索引器、事件、构造函数、析构函数等。

方法:描述对象的行为;

构造函数:初始化对象。无返回值类型,连void都没有,名称和类同名,在创建对象时自动调用的;

析构函数:主要用来回收类的实例所占用的资源,所在类名前加"~"来命名。在对象销毁之前,.NET的公共语言运行时会自动调用析构函数并使用垃圾回收器对对象所占用的内存空间;

析构函数的特点有:不能在结构中定义析构函数,只能对类使用析构函数;一个类只能有一个析构函数;无法继承或重载析构函数;析构函数既没有修饰符,也没有参数;在析构函数被调用前,.NET的CLR自动添加对基类Object.Finalize方法的调用以清理现场,因此C#不允许定义空的析构函数;

属性:保护字段,对字段的取值和设值作相应的限定和逻辑判断。分类:读写,只读,只写。属性为只读时,可以省略set访问器,属性为只写,可以省略get访问器;可读可写就不能省略两个访问器;

索引器:通过索引器从对象中获取数据,一般用于对对象中容器类的数据元素的一种访问。索引器是给对象用的;

事件:又称消息表示向对象发出的服务请求;

C#索引器例子

using System;

public class MyCollection
{
    private string[] data = new string[10];

    // 索引器的定义
    public string this[int index]
    {
        get
        {
            if (index >= 0 && index < data.Length)
            {
                return data[index];
            }
            else
            {
                throw new IndexOutOfRangeException("索引超出范围");
            }
        }
        set
        {
            if (index >= 0 && index < data.Length)
            {
                data[index] = value;
            }
            else
            {
                throw new IndexOutOfRangeException("索引超出范围");
            }
        }
    }
}

class Program
{
    static void Main()
    {
        MyCollection collection = new MyCollection();

        // 使用索引器设置值
        collection[0] = "第一个元素";
        collection[1] = "第二个元素";

        // 使用索引器获取值并打印
        Console.WriteLine(collection[0]);
        Console.WriteLine(collection[1]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

C#清理资源例子 :使用Finalize和IDisposable结合的方式来清理托管资源和非托管资源。

class MyClass : IDisposable
{
    private IntPtr unmanagedResource;
    private bool disposed = false;

    public MyClass()
    {
        unmanagedResource = new IntPtr(123);
    }

    // 实现 Dispose 方法
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    // 重写 Finalize 方法
    ~MyClass()
    {
        Dispose(false);
    }

    // 释放资源的核心方法
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // 释放托管资源
                // 如果有托管对象需要释放,在这里处理
            }

            // 释放非托管资源
            if (unmanagedResource != IntPtr.Zero)
            {
                unmanagedResource = IntPtr.Zero;
            }

            disposed = true;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
托管资源和非托管资常见的托管资源包括:
常见的托管资源包括:

对象:所有使用 new 创建的类实例(例如:string, List<T>, Dictionary<K,V> 等)。
数组:托管数组,例如 int[], string[] 等。
CLR 管理的类型:如 System.IO.Stream, System.Data.SqlClient.SqlConnection(即使它们可能还依赖于非托管资源)。

常见的非托管资源包括:

内存:通过指针分配的内存(例如:使用 IntPtr 或 unsafe 代码)。
文件句柄:操作系统分配的文件或设备句柄。
数据库连接:与数据库交互时分配的连接句柄。
网络资源:如 TCP 连接、网络套接字等。
外部库/组件:例如使用 P/Invoke 调用的 C++ 库,或直接与操作系统接口交互的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13

◆ 方法的参数传递:在声明方法时,定义的参数是形参,调用方法传递的是实参。方法的参数有以下四种类型:值类型不包含任何修饰符;引用类型用ref修饰符声明;输出参数用out修饰符声明;数组用params修饰符声明。

◆ 值类型参数:调用方传递值类型参数时,调用方将把实参变量的值赋给相对应的形参变量,即实参变量和形参变量是两个不同的变量。实参变量的值传递给形参变量时是一种单向值传递。

◆ 引用型参数:调用方给方法传递引用类型参数时,调用方将把实参变量的引用赋给相对应的形参变量。如果在方法内部更改了形参变量所引用的数据值,则同时也修改了实参变量所引用的数据值。

◆ 输出参数:方法中的return语句只能返回一个运算结果,虽然也可以使用引用类型参数返回计算结果,但要求先初始化实参;而输出参数不需要对实参进行初始化,它专门用于把方法中的数据通过形参返回给实参,但不会将实参的值传递给形参。一个方法中可允许有多个输出参数;C#通过out关键字来声明输出参数,无论是形参还是实参,只要是输出参数,都必须添加out关键字。

◆ 数组参数:把数组作为参数,有两种使用形式,一种是在形参数组前不添加params修饰符;另一种是在形参数组前添加params修饰符。两种形式的区别:不添加params修饰符时,所对应的实参必须是一个数组名;添加params修饰符时,所对应的实参可以是数组名,也可以是数组元素值的列表。值得注意的是,无论采用哪一种形式,形参数组都不能定义数组的长度。

◆ 方法重载:是指在同一个类型中,以同样的名称声明两个或多个方法。当需要以不同的参数列表执行同样的操作时,方法重载将会很有用。

◆ 静态类的定义:静态类使用static关键字来声明,表明它仅包含静态成员。不能使用new关键字创建静态类的实例;在实际应用中,当类中的成员不与特定对象关联的时候,就可以把它创建为静态类。

◆ 静态类的主要功能:静态类仅包含静态成员;静态类不能被实例化;静态类是密封的;静态类不能包含实例构造函数。

◆ 静态类的优点:编译器能够自动执行检查,以确保不添加实例成员;静态类能够使程序的实现更简单、迅速,因为不必创建对象就能调用其方法。注意:因为静态类是密封的,因此不可被继承。另外,静态类不能包含实例构造函数,但仍可以声明静态构造函数,以分配初始值或设置某个静态状态。

◆ 静态类的适用性:常用(项目中频繁使用)算法,且该算法不依赖对象。可以将该算法做为静态的。多个对象共同维护同一数据,且该数据在对象间共享,这个数据可以做为静态。静态构造方法,初始化静态成员。工具类常常设置成静态的,比如Math类、Console类。

◆ 静态成员:静态成员使用static关键字来标识,它可以是静态方法、字段、属性或事件。静态成员属于类而不属于类的实例。因此,静态成员都是通过类而不是通过类的实例来访问。静态类中只包含静态成员;非静态类中可以包含静态成员,也可以不包含静态成员。在实际应用中,当类的成员所引用或操作的信息是关于类而不是类的实例时,就应该设置为静态成员。

◆ 静态构造函数:静态构造函数不是为了创建对象而设计的,只有非静态的构造函数才用来创建对象(用于创建对象的构造函数称为实例构造函数)。由于静态构造函数并不对类的特定实例操作,所以也称为全局或共享构造函数。C#应用程序不能直接调用静态构造函数。静态构造函数在类的第一个实例创建之前,或者调用类的任何静态方法之前执行,而且最多执行一次。因此,静态构造函数适合于对类的所有实例都用到的数据进行初始化。

# 面向对象编程高级

◆ 分而治之:就是把复杂的问题简单化,化整为零,大问题分解成若干小问题。

◆ 高内聚,低耦合:对象内部是一个严格的整体(内聚),而对象的外部是相对低耦合的,对象之间的关系要尽量简单。

◆ 封装、继承、多态:

封装:就是把相关的数据和行为包装在一起成为某一事物的一部分,给数据和算法界定一个范围。这是从小角度来说明封装的,从大的角度来说,把多个对象包装成组件,多个组件包装成服务,多个服务包装成应用就是从大的角度来说明封装特性的。封装就是把对象的全部属性和全部服务结合在一起形成一个不可分割的独立单位;封装是一种信息隐蔽技术,用户只能见到对象封装界面上的信息,对象内部对用户是隐蔽的;封装的目的在于将对象的使用者和设计者分开,使用者不必了解对象行为的具体实现,只需要设计者提供的消息接口来访问该对象

继承:世间万物分出层次,分成一些大的类别便于管理众多的不同对象。抽象概念里具有的特征一定是该类中具体对象一定都具有的特征。一类事物的顶层所具有的信息会越来越少,但对于下层的具体对象都是通用的,继承具有单根性和传递性。子类不继承父类的构造函数,但子类会默认的调用父类的无参构造函数,让子类可以使用父类中的成员。如果要显示的调用父类的构造函数需要使用base来调用;

继承的优点和缺点:代码重用,概念重用。继承可以让类实现层次化管理。缺点:继承使类与类的耦合度更高;父类的变化会影响子类的变化;如果子类继承了父类,则该类只能转换为父类;

工具类一般是不需要继承的。特殊类的对象拥有其一般类的全部属性和服务,称作特殊类对一般类的继承,即在特殊类中不必重新定义已在一般类中定义过的属性和服务,这种特性在面向对象中称作对象的继承性。继承在C#中称为派生,其中,一般类称为基类或父类,特殊类为派生类或子类。继承机制的优势在于降低了软件开发的复杂性和费用,使软件系统易于扩充

多态:不同的对象使用不同的方法来实现同一个目标。实现同一个目标来使用不同方法。殊途同归、条条大道通罗马。方法重载也是多态的一种表现。多态性是指在基类中定义的属性或服务被派生类继承后,可以具有不同数据类型或表现出不同的行为。为了实现多态性,需要在派生类中更改从基类中自动继承来的数据类型或方法。这种为了替换基类的部分内容而在派生类中重新进行定义的操作,在面向对象概念中称之为覆盖。多态性的优势在于使软件开发更加方便,增加程序的可读性

◆ 抽象类和抽象方法解释:父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。抽象方法是不允许有方法体的。抽象方法的用途在于设计上,不在于使用上。父类不实现,而将实现推迟到了子类。子类实现了父类的抽象方法时必须的完成该方法体的实现。抽象类不能创建对象,抽象类天生就是用来当爹的类,就是为了规划他的子类的一系列规范。决定了子类应该做些什么。抽象类不能创建对象,抽象类中只能有抽象方法。一般类继承抽象类。子类实现父类中的方法需要在方法前需要加override关键字,表示重写该方法。抽象方法是用斜体字表现区别的。抽象类貌似领导,是做决策的。

◆ 抽象类总结:

形态上:被标识为abstract的类就是抽象类;

语法上:抽象类不能创建对象,只能做基类。抽象类中可以包含抽象成员和实例成员;

语义上:表示类的抽象,表示一个抽象概念,无法表达具体实例。

◆ 抽象方法总结:

形态上:被标识为abstract的没有具体实现的方法;

语法上:抽象方法没有实现,将实现推迟到子类,在子类中以重写(override)的方式实现。抽象方法在子类中必须被实现,除非子类也是抽象类。抽象方法只能出现在抽象类中;

语义上:抽象方法表达行为的抽象,只描述行为规则,不描述行为的实现。抽象方法的作用是为了统一子类的行为。只考虑做什么事,不考虑这个事怎么做,怎么做的事情由子类来完成。就像生活中的具体问题具体对待。

◆ 继承总结:

继承的优点:1、代码重复使用;2、概念复用;3、层次化的方式组织类结构;4、自上而下统一和规范类;

继承的缺点:1、继承使类与类之间的耦合度提高;2、父类的变化直接影响到子类;3、如果子类继承了父类,则该类只能转换为父类类型;

什么东西会继承:类中除了private外的实例成员都会继承给子类。继承尽量选择抽象类;

子类与父类表达的含义:is as的关系;

继承中的构造方法:1 创建子类对象时,先调用父类构造方法,再调用子类的构造方法。2 子类无参构造时,默认会调用父类的无参构造方法。如果父类没有无参构造方法,解决方法a.为父类增加无参构造方法。b.在子类无参构造调用父类的有参构造函数。3。base在子类中出现则表示父类对象。4。base()表示调用父类构造方法。

◆ 多态总结: 一个行为不同的实现。

◆ 虚方法:

可以重写,给子类提供了重写的可能性。父类的方法适合就不用重写,反之重写。重写时用override关键字;

语法:用virtual修饰的方法。子类如果重写了父类的虚方法,子类调用的是重写后方法。抽象方法是虚方法的一种特殊情况;

语义:表示一个可能在实现上有变化的行为,一般类型中提供的方法可能对具体类型不再适用,为了适应具体的类型,在一般类型中将该行为声明为虚的,以便为具体类型提供重写的可能。以满足具体类型不适用的问题。虚方法的调用比实方法的调用要慢。

◆ 方法重写:

override修饰符重写方法。方法重写是动态绑定。目标一致只是手段不同而已。

◆ 方法隐藏:

父类继承的方法在子类中不适用,且方法不能重写。使用关键字new把父类的旧方法隐藏了,但不是重写。方法隐藏只是针对于子类型的;

方法隐藏也是多态的一种体现,相比重写多态不够彻底;

方法隐藏是静态绑定。

◆ 动态绑定和静态绑定:

动态绑定:晚期绑定,方法的调用,调用父类还是子类定义的方法,由创建的对象决定(对象是在程序执行时出现的,所以称为动态绑定);

静态绑定:早期绑定,方法的调用,调用父类还是子类定义的方法,由引用的类型决定(调用方法在编译期间就可以确定,所以称为静态绑定),静态绑定的执行速度快于动态绑定。

# 面向对象思维

◆ 架构师了解的是整个行业,了解一个项目中需要用哪些技术,考虑到好多决策上的问题。

◆ 不变的永远是变化。

◆ 搞技术的眼里不能只有技术。

◆ 重构、单元测试、调试。

◆ 面向对象分析:识别对象 、分配职责、确定关系。

◆ 方法要尽可能的小短,最好是在10行以内,便于阅读和维护。

◆ xml在编程的地位就像是生活中的空气。

◆ 设计类时,尽量不要有重复的代码,因为重复的越多修改时就越费事。

# C#.NET能够开发的应用程序种类

◆ Windows应用程序。

◆ Web应用程序。

◆ Web服务。

# VS快捷键

Ctrl+F5 直接运行程序

Ctrl+E+D 格式化编辑文本

Ctrl+E+C 注释选中的行

Ctrl+K+U 取消注释

Cw+Tab+Tab 相当于Console.WriteLine();

For+Tab+Tab 相当于 for(int i=0;i<10;i++)

Ctrl+鼠标光标放在要拷贝的语句上 整行拷贝

Shift+鼠标光标放在要删除的语句上 整行删除

Ctrl+Shift+V 可以切换粘贴已经拷贝过的所有语句

ALT+鼠标滑动选择 可以选中多行中的某一部分

Home End键 行首和行尾

#region和 #endregion 区块

F12 定位到方法定义

ALT+SHIFT+F10 导入类的命名空间

Ctrl+R+E 封装Get、Set属性

上次更新: 2025/03/22, 13:47:44
最近更新
01
Git问题集合
01-29
02
安装 Nginx 服务器
01-25
03
安装 Docker 容器
01-25
更多文章>
×
×