C#基础知识


1面向过程,面向对象

面向过程:面向的是完成这件事儿的过程,强调的是完成这件事儿的动作

[每一个对象完成相同或者不同的内容,每一个对象内部都可能会有差异性,当要改变某项功能时,不是把所有的程序相关内容改变,而是改变对象的内部性质,或者直接换个对象。屏蔽不同对象完成某一特定功能的差异]

把大象塞进冰箱里

1、打开冰箱门

2、把大象塞进去,亲下大象的屁股

3、关闭冰箱门

孙全                           翟盼盼

孙全踩着凳子打开冰箱门         翟自己打开冰箱门

孙全找人把大象塞进冰箱         翟自己把大象塞进冰箱门

孙全踩着凳子关闭冰箱门         翟自己关闭冰箱门

如果我们采用面向过程的思想来解决这件事情,当执行过程的人不同的时候,我们需要为不同的人量身定做一套不同的方法

面向对象:找个对象帮你做事儿【屏蔽人与人的不同】

把大象塞进冰箱里

我们把冰箱作为对象:

1、冰箱门可以被打开

2、大象可以被塞进冰箱里

3、冰箱门可以被关闭

孙全            翟盼盼

孙全  1        翟    1

孙全  2        翟    2

孙全  3        翟    3

面向对象:意在写出一个通用的代码,屏蔽差异。面向过程过分强调人的存在

关门

面向过程:关门

张三 一脚把门踹紧了

李四 轻轻的把门带上了

王五 门没关严,留了个尾巴

面向对象:关门

门可以被关闭

将圆圈作为对象:这个圆圈可以被画在黑板上。

黑板作为一个对象:可以被画圆圈  被画方块 被画正方向

【一般选被动为对象】

试着描述孙全和颜XX的特征和行为

姓名:孙全

性别:男

身高:180cm

体重:70kg

年龄:22岁

吃喝拉撒睡一切正常 健康

吃喝嫖赌抽

姓名:颜XX

性别:男

身高:180cm

体重:70KG

年龄:23岁

脑残 身体一切健康

我们在代码中描述一个对象,通过描述这个对象的属性和方法

对象必须是看得见摸得着的

灯:属性和方法

属性:

外形:长的

亮度:500W

颜色:白色

牌子:XX

方法:发光

电风扇:属性、方法

外形:三个扇叶

颜色:白色

品牌:XX

方法:转动,扇风

我们把这些具有相同属性和相同方法的对象进行进一步的封装,抽象出来 类这个概念。

类就是个模子,确定了对象应该具有的属性和方法。

对象是根据类创建出来的。

类就是一个盖大楼的图纸   对象 就是盖出来的大楼。

2、类

语法:

[public] class 类名               

         字段;

         属性;

         方法;

}           结构是面向过程的东西(不具备面向对象的三大特征),类是面向对象的东西

写好了一个类之后,我们需要创建这个类的对象,

那么,我们管创建这个类的对象过程称之为类的实例化。

使用关键字 new.

this:表示当前这个类的对象。

类是不占内存的(静态类除外),而对象是占内存的(实例化一个对象后,类中的字段是具有默认初值的)。

3、属性

属性的作用就是保护字段、对字段的赋值和取值进行限定。

属性的本质就是两个方法,一个叫get(当输出属性的值的时候,会执行get方法)

一个叫set(当给属性赋值的时候,首先执行set方法)。

既有get()也有set()我们诚之为可读可写属性。

只有get()没有set()我们称之为只读属性

没有get()只有set()我们称之为只写属性

 

【虽然是给属性赋值,其实也是给字段赋值(属性起到中间过渡的作用,可对值进行限定)//只有给属性赋值,才会实现里边的方法
(限定方法)】

Field字段    Method方法    Property属性

****字段就是女人  属性才是男人。【不能让外界随便访问到字段】

4、访问修饰符

public:公开的公共的,在哪都能访问。

private:私有的,只能在当前类的内部进行访问,出了这个类就访问不到了。

5、初始化

当我们创建好一个类的对象后,需要给这个对象的每个属性去赋值。

我们管这个过程称之为对象的初始化。

6、静态和非静态的区别

1)、在非静态类中,既可以有实例成员(非静态),也可以有静态成员。

2)、在调用实例成员的时候,需要使用对象名.实例成员;

    在调用静态成员的时候,需要使用类名.静态成员名;

总结:静态成员必须使用类名去调用,而实例成员使用对象名调用。

           静态函数中,只能访问静态成员,不允许访问实例成员。

      实例函数中,既可以使用静态成员,也可以使用实例成员。

      静态类中只允许有静态成员,不允许出现实例成员。

使用:

1)、如果你想要你的类当做一个"工具类"(经常使用)去使用,这个时候可以考虑将类写成静态的。(调用时方便)

2)、静态类在整个项目中资源共享。(静态类越少越好)

只有在程序全部结束之后,静态类才会释放资源。(始终消耗资源)

堆  栈  静态存储区域 (谁都可以访问)   例子:【QQ与其中的邮箱等用户名密码不用重复输入】

释放资源。GC Garbage Collection垃圾回收器

7、构造函数

作用:帮助我们初始化对象(给对象的每个属性依次的赋值)

构造函数是一个特殊的方法:

1)、构造函数没有返回值,连void也不能写。

2)、构造函数的名称必须跟类名一样。

创建对象的时候会执行构造函数(可以使主函数减少代码,不用每创建一个对象都赋值)

构造函数是可以有重载的。方便快捷的对一个对象进行初始化。

***

类当中会有一个默认的无参数的构造函数,当你写一个新的构造函数之后,不管是有参数的还是无参数的,那个默认的无参数的构造函数都被干掉了。

8new关键字

Person zsPerson=new Person();

new帮助我们做了3件事儿:

1)、在内存中开辟一块空间

2)、在开辟的空间中创建对象

3)、调用对象的构造函数进行初始化对象

9this关键字

1)、代表当前类的对象

2)、在类当中显示的调用本类的构造函数  :this

过程本质还是调用全参构造函数,没有的默认值,通过this来传递值

10.析构函数

~类名()      程序结束时程序被执行,帮助我们“马上”释放资源

11.命名空间(namespace

解决类重名问题,可以看作类的文件夹

可以认为类是属于命名空间的。

如果在当前项目中没有这个类的命名空间,需要手动导入这个类所在的命名空间。

       1.鼠标去点2.alt+shift+f10 3.记住命名空间,手动的去引用

在一个项目中引用另一个项目中的类

       1.引用-添加引用2.引用命名空间

12.值类型和引用类型

区别1.值类型和引用类型在内存上存储的方式不一样2.在传递值类型和引用类型的时候,传递的方式不一样

(值类型称之为值传递,引用类型称为引用传递)

我们学的值类型和引用类型

值类型:int double bool char  decimal struct enum

引用类型:string 数组 自定义类  接口Icomparable

存储:值类型存储在内存的栈中,引用类型存储在内存的堆中(在栈中存储在堆中的地址)

13.字符串

     1.字符串的不可变性,当你给一个字符串赋值之后,老值并没有销毁,而是重新新开辟一块新的空间存储新值

当程序结束后GC扫描整个内存,如果发现有的空间没有被指向,则立即把他销毁

string s1 = "123";

string s2 = "123";

Console.ReadKey();

在堆中的地址是一样的指向同一个地方,在栈中不一样

2.我们可以将字符串看成是char类型的一个只读数组可以通过下标去访问字符串中的某一个元素

虽然是只读的,但是可以ToCharArray();将字符串转换为char数组

new string(char[] chs )将char数组转换为字符串

14.字符串的方法

1.Length可以获得字符串的个数

2.stringbuilder

在内存中没有开空间,所以比起string更快,对字符串进行大量换之外的操作时,使用stringbuilder,最后转换为string类型(ToString)

【一切类型都可以调用Tostring方法来转换为字符串类型】

3.stopwatch需要引用命名空间(计时器)

Stopwatch(using System.Diagnostics; //添加计时器的命名空间)

Elapsed  获取当前所选的运行时间           Append追加

4.toUpper字符串转换为大写形式的副本(tolower小写)

if(n1.Equals(n2,StringComparison.OrdinalIgnoreCase))

Equals比较两字符串是否相同。OrdinalIgnoreCase忽略大小写

split分割:(返回字符串类型数组)

string f = "a s d+ 1 , + =";

char[] res = { '+', '=',',' };

string[] co=f.Split(res,StringSplitOptions.RemoveEmptyEntries); (不包括空字符串)

Replace 字符串替换za=za.Replace("wudi", "人才");

Substring截取字符串,从指定的下标开始截取,包含指定的下标的字符串

截取指定的下标到指定的长度

bool startswith/endswith判断字符串是否以子串value开始结束

containswith是否包含

IndexOf看字符串第一次出现的位置,如果没有返回-1  (startindex搜索启始位置)

LastIndexOf,最后一次出现的位置,如果没有返回-1

trim去除前面和后面的空格,没有中间trimstart/trimend去掉前面或者后面的空格

IsNullOrEmpty判断字符串是null或者空

Join串联元素,并且在期间放入分隔符(第一个元素是要放入的分隔符)返回一个字符串

File.ReadAllLines(path)打开一个文件,读取文件所有行,返回一个string数组(引用using system.IO)

15.继承

在类中写一些重复的成员(派生类),可以将这些重复的成员单独封装在一个类中,这个类就是父类(基类)

可以通过继承来使用父类中的东西

子类继承了父类,那么从父类继承了啥?

属性,方法,没有私有字段

子类并没有继承父类的构造函数,但是,子类会默认的调用父类无参数的构造函数,创建父类对象

(在创建子类对象的时候,首先会在子类的内部创建一个父类的对象出来,调用父类默认构造函数,才可以使用父类中的东西)

让子类可以使用父类中的成员。

所以,如果在父类中重新写了一个有参数的构造函数后,那个无参的就被干掉了,子类就调用不到了,所以会报错。

解决方法:在父类中重新写一个无参构造函数。(一般不这样,无法节省代码)

在子类中显示的调用父类的构造函数,使用关键字:base()节省代码

16.继承的特性

    1.继承的单根性(一个子类只能有一个父类)

2.继承的传递性(逐渐传递,过程都可以有,逐渐增多)

17.查看类图

项目-查看-查看类图

18.object类是所有类的基类

19.new关键字

    1.创建对象

    2.隐藏从父类继承的同名方法(结果,子类调用不到父类中的成员)

20.里氏转换

   1.子类可以赋值给父类(如果一个地方需要一个父类作为参数,我们可以给一个子类代替)

   2.如果父类中装的是子类对象,那么可以将这个父类强转为子类对象(转换用is判断)

21.

子类对象可以调用父类中的成员,但是父类对象永远只能调用自己的成员

22.isas

is表示类型转换,如果能够转换成功,则返回一个true,否则返回一个false

  as表示类型转换,如果能够转换则返回对应的对象,否则返回一个null

23.protected

受保护的,可以在当前类的内部以及该类的子类中访问

24.ArrayList(需要导入命名空间using System.Collections;

创建了一个集合(很多数据的一个集合)集合的好处:长度可变,类型随便

增加Add,添加集合(数组)使用addrange

插入Insert,在指定默认隐藏下标插入任何元素

删除Remove,删除单个元素,写谁就删谁RemoveAt删除的是默认隐藏下标的元素

RemoveRange删除的是指定范围内的默认下标得的元素

清空Clear,

排序Sort,反转Reverse(升序和反序,里边的元素最好相似)

Contains看是否包含某个元素,返回值是bool类型

ArrayList集合的长度问题(int类型)

每次集合中实际包含的元素个数(count)超过了可以包含的元素的个数(capcity)的时候,

集合就会向内存中申请多开辟一倍的空间,来保证集合的长度一直够用。

25.Hashtable

键值对集合  字典  孙    sun---孙  需要导入命名空间(using System.Collections;)

在键值对集合当中,我们是根据键去找值的。

yu[9] = "景昊煜";        //(不会抛异常,相同的键,会覆盖)这也是一种添加数据的一种方式(键值对集合当中,键必须是唯一的,而值是可以重复的)

键值对对象[键]=值;

*****:键值对集合当中,键必须是唯一的,而值是可以重复的

Keys可以根据键找到其中的值ContainsKey是否包含键值

Clear();     //移除集合中的所有元素

Remove();     //移除带有指定键的元素

Var推断类型

C#是一门强类型的语言:在代码中必须对每一个变量的类型有一个明确的定义

js是一门弱类型的语言:在代码中不需要对变量的类型有一个明确的定义,所有都用var

GetType(获取变量类型)

var:根据值推断类型,用var必须赋值,所以基本不用var推断类型

26foreach循环

foreach (var item in collection)

 {

 }

collection:要循环的数组或者集合

item:数组或者集合中的元素

(与for循环区别,在循环次数比较大时,foreach循环效率更高)

27、编码格式

产生乱码的原因就是因为你保存这个文件的编码格式跟你打开这个文件的编码格式不一样。

28、文本文件

拖到txt文件中,还能看得懂的文件就是文本文件。

29.Path类路径操作方法using System.IO;

Path.GetFileName快速的获得一个路径下的文件名字

Path.GetFileNameWithoutExtension获取一个路径下的文件,但是不包含扩展名

Path.GetExtension获取一个路径下的文件扩展名

Path.GetDirectoryName获取文件所在文件夹的名称

Path.GetFullPath获取全路径

Path.Combine将两个字符串组合为两个路径

30.fileusing System.IO;

只能读取小文件(一下子全读),大文件需要用到文件流

创建文件路径及名称File.Create

删除文件File.Delete

复制一个文件到新的路径的新的文件名File.Copy

1024byte=1kb     1024kb=1M  1024M=1G  1024G=1T  1024T=1PT

File.ReadAllBytes:

打开一个文件,将一个文件中的内容读入一个字符串,然后关闭该文件

将字节数组中的每一个元素都要按照我们指定的编码格式解码成字符串,Encoding.GetEncoding("UTF-8").GetString(qw);

File.WriteAllBytes:

没有这个文件的话就创建一个,有的话就覆盖

byte[] s=Encoding.Default.GetBytes(n);将相应的字符串转换为字节

File.ReadAllLines:【返回的是数组】

打开一个文件。读取文件的所有行,关闭文件(以行来读取(可以精确的操作每一个数据))

File.ReadAllText

打开一个文件,使用指定的编码读取文件的所有行,然后关闭该文件

File.WriteAllLines:

创建一个新文件,在其中写入指定的字符串数组,然后关闭该文件

File.WriteAllText:

创建一个新文件,在其中写入指定的字符串,然后关闭该文件。如果文件已经存在,就覆盖。

File.AppendAllText:

打开一个文件,向其中追加指定的字符串,然后关闭该文件。如果文件不存在,那么此方法创建一个文件,写入指定的字符串数组,然后关闭该文件

31.绝对路径和相对路径

绝对路径:通过给定的这个路径直接能在我的电脑中找到这个文件。

相对路径:文件相对于应用程序的路径。

结论:

我们在开发中应该去尽量的使用相对路径。

32.List泛型集合

创建泛型集合对象(类型确定)长度可以任意改变//clear remove reverse sort insert

Add  Addrage

list泛型集合可以转换为数组(数组也可以转换为集合)ToArray  ToList

33、装箱、拆箱

装箱:就是将值类型转换为引用类型。

拆箱:将引用类型转换为值类型。

看两种类型是否发生了装箱或者拆箱,要看,这两种类型是否存在继承关系。

34.dictionary字典集合

键值对,键和值的类型确定

KeyValuePair<>字典遍历方式为一对

35.FileStream读取数据

使用FileStream读取数据

File全读   Filestream一点一点读(操作【字节】的,代表可以操作任何类型的文件)

StreamWriter   StreamReader(操作【字符】的)只能操作文本文件

FileMode:操作系统打开文件的方式

FileAccess:文件读取或写入权限常数

创建一个FileStream对象----然后创建一个字节数组---读取这个字节数组---返回读取的存储,将字节数组中每一个元素按照指定的编码格式解码成字符串---关闭流---释放流

(字节转字符串)

将创建文件流对象的过程写在using当中,会自动的帮助我们释放流所占用的资源

Using后加创建文件流对象---要写入的东西---将此转换为字节数组---然后规定写入的长度

(字符串转字节)

36.  StreamReaderStreamWriter

StreamReader以行来读取一个文件EndOfStream(判断是否读取到了流的末尾)所以while循环一直读取

StreamWriter:加true看是否是追加

37.  实现多态的手段

1)、虚方法

步骤:

1、将父类的方法标记为虚方法 ,使用关键字 virtual,这个函数可以被子类重新写一个遍。子类override

(减少代码,增加可扩展性,一个父类对象可以表现出多种状态)

2)、抽象类

当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。

抽象类和接口都不能创建对象

抽象方法不能有方法体(存在的意义就是使子类方法重写)

【虚方法和抽象类区别是看父类有无实现】

1.抽象成员必须标记为abstract,并且不能有任何实现。

2.抽象成员必须在抽象类中。

3.抽象类不能被实例化

4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。

(除非子类也是一个抽象类,则可以不重写)

5.抽象成员的访问修饰符不能是private

6.在抽象类中可以包含实例成员。

并且抽象类的实例成员可以不被子类实现

7.抽象类是有构造函数的。虽然不能被实例化。

 

8、如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。

 

如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。

 

 

======

如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。

 

如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。

 

3).接口

38.  访问修饰符

public:公共的,共有的,哪儿都可以访问

private:私有的,只有在当前类的内部可以访问

protected:受保护的,只能在当前类的内部以及该类的子类访问

internal:只能在当前项目(程序集)中访问。(在同一项目中public 和internal的权限是一样的)

protected internal:protected+internal

        1.能够修饰类的访问修饰符有:public internal

        2.可访问性不一致:子类的访问权限不能高于父类的访问权限,会暴漏父类的成员

39.  设计模式

设计这个项目的一种方式

简单工厂设计模式:简单工厂的核心,根据用户的输入来创建对象赋值给父类

40.  值传递和引用传递

值类型在复制的时候传递的是这个值的本身

引用类型在复制的时候,传递的是对这个对象的引用

41.序列化和反序列化

序列化:就是将对象转化为二进制

反序列化:就是将二进制转化为对象

作用:传输数据

序列化:

  1. 将这个类标记为可以被序列化的[Serializable]写在类的上面

序列化所必需的BinaryFormatter(需引用命名空间).Serialize

反序列化:.Deserialize

42.部分类

不能包含有两个相同的类,但是partial是部分类,两个部分person类共同组成了person类(其中私有和共有都可以共用)

43.密封类sealed

密封类不能够被继承,但是可以继承其他类

44.  接口

一个类继承一个接口,必须实现其中的方法,一个子类只能继承一个父类,但是可以多一个接口多继承的时候使用接口,接口就是一个规范,能力

【public】 interface    I.......able

      成员;

接口中的成员不允许有访问修饰符,默认为public (类中不加public默认为private)

接口中的成员也不会有方法体(接口成员不能有定义),接口中不能包含字段,可以有自动属性(虽然不写字段,但是在编译时自动生成一个私有字段)

接口中可以有1方法 2属性 3索引器

接口不能被实例化,因为没有意义,接口与接口之间可以多继承

当一个类继承接口的时候,出现方法名重名问题(显示实现接口就是为了解决方法的重名问题)

void 接口名.方法()

45.Socket:

有两种协议TCP:有三次握手,传输稳定,但是效率低

UDP:传输效率高,但是不够稳定(一般视频
时)人通过电话进行通讯,程序间通过socket进行

通讯,Socket相当于电话,HTTP相当于语言。

C