- Main函数是什么?
- 在程序中使用Main函数有什么需要注意的地方?
- CLR是什么?
- 程序集是什么?
- 当运行一个程序集的时候,CLR做了什么事情?
- 值类型的默认值是什么?
- 声明一个变量时在内存中做了什么事情?
- 初始化一个变量的时候又在内存中做了什么事情?
- new关键字做的事情?
- 数组一旦创建后,能不能修改数组的长度?
- 如何声明一个多维数组?
- 如何获取多维数组的总长度?
- 如何声明一个交错数组?
- 交错数组的本质是什么?
- 为什么要有方法?
- 如何实现方法的重载?
- 引用参数(ref)和输出参数(out)的相同点与不同点?
- 在什么情况下使用引用参数(ref)和输出参数(out)?
- 可变参数与普通数组参数的区别?
- 面向对象的三大特征是什么?
- 类和对象的关系?
- 创建某一个类的对象的时候,在内存中做了什么事情?例如 Person p = new Person();
- 属性存在的目的是什么?
- 访问修饰符有哪些并分别每一个访问修饰符?
- 为什么要有构造函数呢?
- 什么是封装?
- 封装的目的是什么?
- 类的命名规则是什么?
- 什么是类型?
- this关键字在方法中使用时,它代表什么?
- 值类型变量的初始化(内存分配)?
- 继承的好处?
- 继承的单根性
- 继承的传递性
- 当存在继承关系的时候,在子类中如何访问父类的非私有成员?
- 什么是里氏替换原则?
- 子类与父类对象之间的转换?
- is 和 as 操作符的用处和区别?
- override可以重写哪些 "类型" 的方法?
- 什么是多态?
- 抽象方法只能定义在抽象类中吗?
- CLR什么时候加载类?
- 当存在继承关系的时候,创建子类对象的时候会不会创建父类对象呢?
- 如果子类和父类存在同名但没有重写关系的方法的时候,那么会调用哪个方法?
- 如果子类和父类存在同名且有重写关系的方法,那么会调用那个方法?
- 虚方法和抽象方法的相同点与不同点?
- 子类中的base关键字指向的是子类对象还是父类对象?
- 它本身的类型是子类类型还是父类类型呢?
- 为什么要有抽象类?
- 使用多态的好处是什么?
- 什么情况下的类不能被实例化?
- 什么情况下抽象类的子类不需要实现父类的抽象成员?
- 虚方法(虚拟成员)和抽象方法(抽象成员)能不能被私有化?
- 静态成员能不能被标记为virtual、override 或 abstract?
- 接口的命名规则?
- 什么是接口?
- 接口能包含的成员有哪些?
- 接口的访问权限修饰符只能是哪两种?
- 接口能不能实现接口?
- 如果一个抽象类继承了一个接口,那么将继承的方法设置为抽象方法,还是去实现该方法?
- 使用接口应注意什么事项?
- 显式接口和隐式接口?
- 接口与抽象类的区别?
- 转换分类?
- ToString()方法?
- Parse()和TryParse()方法的区别?
- 什么时候加载静态成员
- 什么时候用静态成员
- 在普通类和静态类中的区别
- 静态类的继承
- 类和成员的访问修饰符
- 结构本质是什么?
- 值类型和引用类型的选择
- new关键字的作用
- 类和结构的区别
- 值类型和引用类型作为参数传递的区别
- 访问级别约束
- 析构函数
- 为什么不能在结构体中定义析构函数
- 字符串常用方法
- ==运算符和Equals()方法的区别
- 字符串的恒定性
- StringBuilder 和 String 的区别?
- 枚举本质是什么?
- 枚举项的相关问题
- IEnumerable接口
- 集合
- 动态数组和 泛型集合的不同点和优缺点
- 泛型list的常用方法
- 哈希表内部机制原理
- 哈希表存取操作原理
- 泛型集合引用命名空间
- List 和ArrayList的性能比较
- 应该使用try语句块的情况
- Windows Form程序相关文件
- Path类相关方法
- 操作目录(Directory类)相关方法
- 操作文件(File)相关方法
- DirectoryInfo(文件夹的一个“类”,用来描述一个文件夹对象)相关方法
- using语句的本质
- 文件操作注意问题
- 序列化和反序列化的区别
- Serializable特性
- 什么是委托?
- 委托的目的是什么?
- 委托的适用情形?
- 冒泡排序?
- 匿名方法是什么?
- 多播委托是什么?
- 事件本质是什么?
- 委托和事件的区别是什么?
- Main函数是什么?
- 在程序中使用Main函数有什么需要注意的地方?
- Main函数不能变,有且只有一
- CLR是什么?
- 公共语言运行时
- Common Language Rentime
- 程序集是什么?
- 编译后代码的集合(包括exe和dll);加载项目里所有的类到内存,并找到其中的主函数,并作为默认的启动函数调用执行
- 当运行一个程序集的时候,CLR做了什么事情?
- 加载项目所有的类到内存,并找到其中的主函数作为默认的启动函数调用执行,但是,如果项目中,包含一个以上的主函数时CLR不知道从那里开始,如果项目中,没有包含主函数的话,CLR也不知道如何启动
- 值类型的默认值是什么?
- 如果没有赋值且是全局变量或字段
- Int默认为0
- Bool 默认为false
- Eumn
- 结构体
- 如果是局部变量就必须赋值
- 如果没有赋值且是全局变量或字段
- 声明一个变量时在内存中做了什么事情?
- 在栈中开辟空间,并将变量放入空间中,默认值为Null
- 初始化一个变量的时候在内存中做了什么事情?
- 如果是值类型直接放在栈中
- 如果是引用类型,在堆中开辟空间,将堆中的地址指针放入栈中
- new关键字做的事情?
- 开辟空间
- 创建对象
- 调用构造函数
- 数组一旦创建后,能不能修改数组的长度?
- 不能,创建时在内存中开辟了一段连续的空间
- 如何声明一个多维数组?
- string[,] strs={{"1","1"},{"1","1"}};
- 如何获取多维数组的总长度?
- 各个纬度元素的乘积
- 如何声明一个交错数组?
- int[] [] arr=new int [3] [3];
- 交错数组的本质是什么?
- 一个数组的数组,也就是数组的元素就是一个一维数组
- 为什么要有方法?
- 为了复用
- 封装具体实现
- 如何实现方法的重载?
- 方法名相同,方法签名不同,和返回值无关
- 引用参数(ref)和输出参数(out)的相同点与不同点?
- 相同点:传递的都是引用
- 不同点:out侧重于输出参数,ref侧重于修改参数,out必须方法返回前赋值,ref必须在传入之前赋值
- 在什么情况下使用引用参数(ref)和输出参数(out)?
- 如果方法有多个返回值,则可以用out或者ref。只不过ref侧重于修改(即将值传进去修改后在拿出来),而out是为了从方法中获得一个值后拿到方法外使用
- 可变参数与普通数组参数的区别?
- 必须放在参数列表最后
- 每个方法中有且只有一个params
- 如果没有给params赋值,长度就自动初始化为0
- 面向对象的三大特征是什么?
- 封装
- 继承
- 多态
- 类和对象的关系?
- 类是抽象的,对象是具体的实现
- 类是用来描述实物的,是针对具体存在的一种描述,对象是这类事务存在的具体实现,按照类的描述来创建一个可供我们使用的实例
- 创建某一个类的对象的时候,在内存中做了什么事情?例如 Person p = new Person();
- 开辟空间,创建对象,调用构造函数(在内存的堆中开辟空间,创建Person对象,然后在内存的栈中开辟一空间放一个p,然后将Person对象在堆中的引用地址赋值给对象p)
- 属性存在的目的是什么?
- 封装字段
- 为了对字段的操作设置规则
- 本质上是两个方法:get();set();
- 访问修饰符有哪些并分别每一个访问修饰符?
- Public 公有的
- private 私有的
- Internal 程序集内共享,如果不写修饰符默认就是Internal
- Protected 受保护的
- Extern 供外部访问
- 为什么要有构造函数呢?
- 主要方便程序员在实例化对象中一些属性字段初始化赋值
- 什么是封装?
- 就是把重复的代码包起来
- 封装的目的是什么?
- 复用
- 隐蔽实现
- 修改方便
- 类的命名规则是什么?
- 帕斯卡方式,首字母大写
- 变量,骆驼命名方式,首字母小写
- 什么是类型?
- 用来定义某一种数据在内存里开辟空间的大小
- this关键字在方法中使用时,它代表什么?
- 所在类的堆里面的对象
- this指当前类的对象,或者他的父类的类对象
- 值类型变量的初始化(内存分配)?
- 当变量是一个类的成员变量的时候,那么该变量是跟随类的对象存在于堆内存,但对象引用断开时,等垃圾回收器进行清理时便销毁
- 继承的好处?
- 提高代码的复用
- 实现多态
- 继承的单根性
- 一个类只有一个父类
- 继承的传递性
- 指子类“获得”父类所有非私有的成员
- 当存在继承关系的时候,在子类中如何访问父类的非私有成员?
- 当存在继承关系的时候,子类的this同时可以指向父类的非私有成员,base就是存在于子类对象里,用来指向父类对象的指针
- 什么是里氏替换原则?
- 在声明的时候,子类替换父类所在的位置
- 子类与父类对象之间的转换?
- 子类可以强转为父类,反之无法实现
- is 和 as 操作符的用处和区别?
- is就是出去对类型的判断,返回true和false。如果一个对象是某个类型或是其父类型的话就返回为true,否则的话就会返回为false,is永远不会抛出异常
- as关键词只能判断、转换引用类型,as首先测试转换是否合法,如果合法就转换,否则返回Null。关键词Null表示空引用,不会抛异常
- override可以重写哪些 "类型" 的方法?
- 虚方法(virtual)
- 抽象方法(abstract)
- 什么是多态?
- 就是用某个子类来实例化父类,调用的是父类的抽象方法(虚方法),但实际执行的是子类实例重写的方法
- 抽象方法只能定义在抽象类中吗?
- 抽象方法只能定义在抽象类中
- 抽象方法必须在子类中实现,除非子类也是抽象类
- 抽象成员不能是私有的(private)
- CLR什么时候加载类?
- 是在第一次在代码中遇到这个类的时候才加载类的静态成员和信息
- 当存在继承关系的时候,创建子类对象的时候会不会创建父类对象呢?
- Person p=new Student()
- 当我们new一个子类的时候,在内存中,只有一个子类对象
- 如果子类和父类存在同名但没有重写关系的方法的时候,那么会调用哪个方法?
- 如果子类和父类存在同名但没有重写关系的方法,那么调用时,如果父类变量调用,则调用父类方法,如果是子类变量调用,则调用子类的方法
- 如果子类和父类存在同名且有重写关系的方法,那么会调用那个方法?
- 如果子类和父类存在同名且有重写关系的方法,那么不管变量是什么类型,调用的都是子类的方法
- 虚方法和抽象方法的相同点与不同点?
- 相同点
- 抽象方法和虚方法都能被重写
- 都不能为private
- 不同点
- abstract和virtual的关键字不同
- 抽象方法一定没有方法体,而虚方法必须有方法体
- virtual方法的子类可以重写父类方法也可以不重写,而抽象方法的所在的类的子类必须重写父类方法
- 抽象方法必须在抽象类中声明,而虚方法可以存在于任何类里面
- 相同点
- 子类中的base关键字指向的是子类对象还是父类对象?
- 子类对象
- 它本身的类型是子类类型还是父类类型呢?
- 父类类型
- base就是子类对象本身,只不过类型是父类的
- 为什么要有抽象类?
- 抽象类存在的目的就是制定规则,而不是具体实现,(为了约束子类的行为),具体实现交给子类完成
- 使用多态的好处是什么?
- 低耦合,代码之间关联小,便于维护
- 作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化
- 什么情况下的类不能被实例化?
- abstart(抽象类)
- static(静态类)
- private(构造函数私有化)
- 什么情况下抽象类的子类不需要实现父类的抽象成员?
- 子类本身也是抽象类
- 虚方法(虚拟成员)和抽象方法(抽象成员)能不能被私有化?
- 不能(编译报错)
- 深层原因:他们两者存在的目的就是为了让子类去重写,如果私有化了就没意义了
- 静态成员能不能被标记为virtual、override 或 abstract?
- 不能
- 接口的命名规则?
- I开头
- able结尾,表示有什么能力
- 什么是接口?
- 特殊的抽象类
- 完全是为了约束类的行为
- 接口能包含的成员有哪些?
- 只能有方法、属性、索引、和事件的声明
- 接口的访问权限修饰符只能是哪两种?
- public
- internal
- 接口能不能实现接口?
- 能实现
- 如果一个抽象类继承了一个接口,那么将继承的方法设置为抽象方法,还是去实现该方法?
- 都可以
- 使用接口应注意什么事项?
- 接口的成员不能加访问修饰符
- 接口的成员不能有任何实现
- 实现接口的子类必须实现接口的全部成员
- 接口中只有方法、属性、事件、索引器,不能有字段
- 一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现接口IA,那么在语法上A必须在写在IA的前面,因为类是单继承的,而接口可以实现多个
- 向上转型
- 单一职责原则:避免定义体积庞大的接口,只把相关联的一组成员定义的接口中,如果不这样做就会造成接口污染
- 显式接口和隐式接口?
- 类实现几口,可以显式的实现接口里的方法,但注意:旦使用显式接口里的方法后,那么该方法只能被接口变量调用
-
IFlyable fly = new Bird();
-
fly.Fly(); //正确
-
Bird fly = new Bird();
-
fly.Fly(); //错误
- 接口与抽象类的区别?
- 抽象类:
- 抽象方法只作声明,而不包含实现,可以看成是没有实现体的虚方法。
- 抽象类不能被实例化。
-
抽象类可以但不是必须有抽象属性和抽象方法, 但是一旦有了抽象方法, 就一定要把这个类声明为抽象类
-
具体子类必须实现基类的抽象方法
-
抽象子类可以实现基类的抽象方法,也可以不实现。如果不实现,则其具体子类必须实现它们
-
接口
- 接口不能被实例化
-
接口只能包含方法声明
-
接口的成员包括方法、属性、索引器、事件
-
接口中不能包含常量、字段(域)、构造函数、析构函数、静态成员
-
接口中的所有成员默认为public,因此接口中不能有private修饰符
-
子类必须实现接口的所有成员
-
一个类可以直接实现多个接口,接口之间用逗号隔开
-
一个接口可以有多个父接口,实现该接口的类必须实现所有父接口中的所有成员
- 抽象类:
- 转换分类?
- 隐式转换
- 显示转换
- ToString()方法?
- 是object对象的一个虚方法,如果不重写就返回类全名称
- 可以重写该方法
- Parse()和TryParse()方法的区别?
- 相同点
- 都是针对值string类型进行的值类型转换
- 不同点
- 返回值不一样,Parse返回转换成功的类型,TryParse返回Bool值
- Parse转换失败会抛异常,TryParse不会抛异常
- Parse通过返回值返回结果,TryParse通过out返回结果
- 相同点
- 什么时候加载静态成员
- 在编译的时候
- 什么时候用静态成员
- 在整个程序内部共享的数据,通常用做通用工具类,比如SQLHelper类
- 在普通类和静态类中的区别
- 静态类用state修饰
- 静态类不能被实例化
- 静态类中只能包含静态成员
- 静态成员属于类所有,非静态成员属于类的实例所有
- 在实例方法中可以直接调用静态成员,而静态方法中不能直接调用实例方法
- 静态类和静态成员创建后始终使用同一块内粗,而使用实例的方式会创建多块内存
- 静态构造函数不能有参数,也不能有访问访问修饰符(默认是Private)
- 静态类的继承
- 不能被继承
- 只能继承Object
- 类和成员的访问修饰符
- 类的访问修饰符只有两种:public,internal(默认)
- 成员的访问修饰符有:public,protected,private(默认)
- 结构本质是什么?
- 结构体的本质是值类型
- 值类型和引用类型的选择
- 值类型:主要是用来封装一组数据,并为数据提供一种简单的处理方式
- 引用类型:
- 主要用来封装数据和行为
- 使用面向对象的特征
- 当类型中的成员比较多的时候(存放在堆里)
- 结构 new关键字的作用
- 使用new关键字创建对象后,所用的成员变量都已经存在,并有默认值(值类型);如果没有用new关键字,则需要程序员手动为用到的成员变量赋值
- 类和结构的区别
- 结构是值类型,是分配在内存的栈上的,而类是引用类型,是分配在内存的堆上的
- 结构不能被继承,因为结构是值类型,隐式继承自System.ValueType
- 结构是值传递的(赋值传递),而类是引用传递的
- 值类型和引用类型作为参数传递的区别
- 结构是值传递的(赋值传递),而类是引用传递的
- 访问级别约束
- 子类的访问级别不能比父类的高
- 类中的属性或字段的访问级别不能比所对应的类型访问级别高
- 方法的访问级别不能比方法的参数和返回值的访问级别搞,比如当方法的参数传递的是一个类的对象时,那么此时这个类的对象的访问级别要高于当前方法的访问级别
- 析构函数
- 一个类只能有一个析构函数
- 无法继承和重载析构函数
- 我们无法手动调用析构函数,因为他是被GC自动调用的
- 析构函数没有访问修饰符也不能有参数
- 不能在结构体中定义析构函数
class MyDispose{~MyDispose(){...//在这里写释放资源的代码}}
- 为什么不能在结构体中定义析构函数
- 因为结构是值类型,而值类型是存储在栈汇总的,栈中的数据在用完之后就立即销毁了,而析构函数就是用泪释放资源的,一般存储在堆中的引用类型才需要GC去释放
- 字符串常用方法
- (Last)IndexOf:用来查找某个字符或者字符串,在一个特定字符串对象里的下标
- SubString:截取
- Split():根据特定字符来分割字符串,并返回分割后的字符串的数组,可以用foreach读取
- Join:静态方法
- Format():静态方法
- Replace():替换完要接收,产生一个新的字符串
- Trim():去首尾空格
- ==运算符和Equals()方法的区别
- "=="如果比较的是值类型,则比较两个对象的值;如果比较的是引用类型,则比较两个对象的引用地址是否相同
- Equals()是Object里的虚方法,默认用==进行比较,但是大部分微软的类,及用户定义的类,都重写了该虚方法,也就是微软和用户各自为自己编写的Object的子类定义了相等比较规则
- 字符串的恒定性
- 当字符串在内存中已经被创建后,程序员在此创建相同值的字符串对象时,CLR做了优化,直接把第一个字符串的引用赋给了第二个变量,也就是说,前后两个字符串变量保存了相同的字符串对象引用
- 如果代码里是直接将两个字符串相加,那么在CLR编译IL的时候,就会直接将相加拼接后的新字符串作为变量的值;如果代码里是将两个字符串变量相加的话,那么,CLR会在编译IL时,调用string.Concat(string,string)方法来将两个字符串变量的值拼接,最后返回一个新的字符串变量
- StringBuilder 和 String 的区别?
- String在进行运算时(如赋值、拼接等)就会产生一个新的实例,而StringBuilder则不会。所以在大量字符串拼接货频繁对某一个字符串及in行操作时最好使用StringBuilder,不要使用String如果要操作一个不断增长的字符串,尽量不用String类,改用StringBuilder类
- 两个类的工作原理不同:String类是一种传统的修改字符串的方式,它确实可以完成把一个字符添加到另一个字符串上的工作没错,但是在.Net框架下,这个操作实在是划不来,因为系统先是把两个字符串写入内存,接着删除原来的String对象,然后创建一个String对象,并读取内存中的数据赋给该对象。这一来二去的,耗了不少事件,而使用System.Text命名空间下面的StringBuilder类就不是这样了,它特工了Append方法,能够在现有对象的基础上进行 字符串的修改,简单而且直接,当然,一般情况下觉察不到这两者的效率差异,但如果你要对某个字符串进行大量的添加操作,那么StringBuilder类所耗费的事件和String类简直不是一个数量级的
- 枚举本质是什么?
- 枚举的本质就是类
- 枚举项的相关问题
- 如果为第一个枚举项赋了一个int值,那么后面的枚举项依次递增
- 可以将枚举强转成他所代表的int值
- 因为枚举项都对应的int值,所以Switch把他当成int看
- C#的枚举项都是常量
- 不能定义方法、属性、事件
- 多个枚举有相同数值时,数值强转时,会返回其中最后一个枚举项
- 枚举项的数值类型int long shot...
- 值类型,因为继承System.ValueType
- IEnumerable接口
- 只要实现该接口就可以使用foreach(封装了迭代器)
- IEnumerable接口主要包含
- GetEnumerable方法(获取迭代器)
- MoveNext方法(检查是否存在循环的下一个元素)
- GetCurrent方法(获得当前循环到的元素)
- 集合
- 主要分为非泛型集合和泛型集合
- 非泛型集合
- Arraylist
- 里面真正存储数据的是一个Object[]数组,它对应的泛型是List<T>
- HashTable
- 非泛型的键值对集合,它对应的泛型是Dictionary<TKey,TValue>
- Arraylist
- 泛型集合
- List<T>
- Dictionary<K,V>
- 动态数组和 泛型集合的不同点和优缺点
- 不同点
- 动态数组对元素没有任何约束,可以添加任何元素,其根本原因是内部存储元素的是一个Object数组
- 泛型集合是带元素类型约束的集合
- 尽可能使用泛型集合
- 优缺点
- 避免了装箱、拆箱操作带来的性能损耗
- 在添加元素时随参数类型进行检查(编译时就检查)
- 不同点
- 泛型list的常用方法
- Add()
- AddRange()
- Insert()
- InsertRange()
- Remove()
- RemoveAt()
- Resverse()
- 哈希表内部机制原理
- 内部就是一个结构体数组(bucket)
private struct bucket
{
public object key;
public object val;
public int hash_coll;
}
{
public object key;
public object val;
public int hash_coll;
}
-
如何存?
- 下标是根据key的hash值算出来的。当我们向Hashtable中Add元素时,元素储存在Hashtable的数组里的下标是根据添加key的hash值算出来的(但因为hash值取模数组长度,所以肯定不会超过当前数组长度)
- 每个对象算出的Hashcode并不是唯一的,有可能出现多个对象的Hashcode相同
-
解决机制
- 再Hash一次
- 桶装模式,将两个相同的Hashcode的对象装入一个位置
- 当新增时,Hashtable里的容器数组已经满了,则以数组的两倍扩容
-
如何取?
- 当我们从Hashtable里取元素时(根据key来取),会根据key的hash值算出要取的元素的下标,并比较元素里的key和当前要找的key参数的hash值是否相等,同时还要比较两个key的引用是否一致,如果都满足,则确定找到要取的元素
-
泛型集合引用命名空间
- System.Collections.Generic
-
List
和ArrayList的性能比较
- 避免装箱、拆箱操作带来的性能损耗
- 在添加元素时随参数类型进行检查(编译时检查)
-
应该使用try语句块的情况
- 网络操作、文件操作、数据库操作、除法操作、强制类型转换操作
-
Windows Form程序相关文件
- designer.cs 设计类和前台两个类是兄弟类的关系
-
Path类相关方法
-
ChangeExtension(修改文件的后缀,“修改”支持字符串层面的,没有真的给文件改名)
-
Combine(将两个路径合成一个路径【自动处理路径分隔符的问题】)
-
GetDirectoryName(得到文件的路径名)
-
GetExtension(得到文件的扩展名)
-
GetFileName(得到文件路径的文件名部分)
-
GetFileNameWithoutExtension(得到去除扩展名的文件名)
-
GetFullPath(得到文件的全路径,可以根据相对路径获得绝对路径)
-
GetTempFileName(得到一个唯一的临时文件名)
-
GetTempPath(得到临时文件夹的路径)
-
-
操作目录(Directory类)相关方法
-
Delete(删除目录【recursive表示是否递归删除】)
-
Exists(判断目录是否存在)
-
move(移动)
-
GetDirectories(得到一个目录下的子目录)
-
GetFiles(得到一个目录下的文件)
-
-
操作文件(File)相关方法
-
AppendAllText(将文本contents附加到文件path中【如果文件不存在,则创建】)
-
Exists(判断文件path是否存在)
-
ReadAllLines(读取文本文件到字符串数组中)
-
ReadAllText(读取文本文件到字符串中)
-
WriteAllText(将文本contents保存到文件path中,会覆盖旧内容)
-
WriteAllLines(将字符串数组逐行保存到文件path中,会覆盖旧内容)
-
Copy(文件拷贝【true表示当文件存在时“覆盖”,如果不加true,则文件存在报异常】)
-
Create(创建文件)
-
Delete(如果文件不存在?不存在,不报错)
-
-
DirectoryInfo(文件夹的一个“类”,用来描述一个文件夹对象)相关方法
- GetParent(得到目录的父目录)
-
using语句的本质
- 就是一个try finally
- 所有要使用using关键字来释放资源的类都必须实现IDisposable接口
-
文件操作注意问题
- 当使用文件流的时候,在关闭流的时候数据才会保存到文件中
- Close执行了Dispose()并回收对象
- 所有要使用using关键字来释放资源的类都必须实现IDisposable接口
- 获取当前exe文件执行的路径用(Assembly.GetExecutingAssembly().Location不要用Directory.GetCurrentDirectory(),因为获取的是程序当前工作目录,这个路径可能会变
-
序列化和反序列化的区别
-
序列化
- 又叫做二进制格式化器,将对象转换成文本--字段、字段值、类名
- Serialize(对象graph序列化到stream中)
-
反序列化
- 按照文本(字段、字段值、类名)信息里的类名,使用反射技术创建新对象,并将对一个的字段值设置到新的对象中
- Deserialize(将对象从stream中反序列化,返回值为反序列化得到的对象)
-
序列化
-
Serializable特性
- 要序列化的类型必须标记为:[Serializable]
- 该类型的父类也必须标记为:[Serializable]
- 该类型中的所有成员的类型也必须标记为:[Serializable]
- 序列化只会对类中的字段序列化(只能序列化一些状态信息)
-
什么是委托?
- 就是一个能够存放与委托类具有相同签名方法的“方法集合”
- 委托本质上就是一个类,继承与MulticastDelegate→Delegate(在Deleagate类中有一个IntPtr类)
- 委托就是一个存放方法指针的容器,是一个安全的函数指针
-
委托的目的是什么?
- 能够将方法作为参数传递
- (多播委托)调用一个委托,执行N个方法
-
委托的适用情形?
- 当方法传递的参数为一个方法时,就用委托
-
冒泡排序?
-
for(int j=0; j<nums.Length-1; j++)
{
for(int i=0;i<nums.Length-1-j;i++)
{
if(nums[i]>nums[i+1])
{
int temp=num[i];
nums[i]=nums[i+1];
nums[i+1]=temp;
}
}
}
-
-
匿名方法是什么?
- 并不是真没有名字,它在CLR编译时会产生一个临时方法名
- 匿名方法产生后,方法指针会存放在委托变量中,供程序调用
-
多播委托是什么?
- 可以向委托上注册多个方法
- 也可以从委托上移除注册方法
- 如果委托上注册了多个有返回值的方法,那么在调用之后委托返回的是最后一个方法的返回值
-
事件本质是什么?
- 本质就是提供一个Add和Remove方法的委托对象
- 是为了约束一个委托对象的操作方法,对外只提供+=和-=操作
- 观察者模式就是事件的体现
-
委托和事件的区别是什么?
- 委托和事件没有可比性,因为委托是类型,事件是对象
-
下面说的是委托的对象(用委托方式实现的事件)和(标准的event方式实现)事件的区别
- 事件的内部是用委托实现的,因为对于事件来说,外部只能“+=注册自己”、“-=注销自己”,外界不可以注销其他的注册者,外界不可以主动触发事件,因为如果Delegate就没法进行上面的控制,因为诞生事件这种语法,事件是用来阉割委托实例的,类比用一个自定义类阉割List。事件只能Add,Remove自己,不能赋值。事件只能+=、-=不能=