面向对象
Q1.面向对象的基本概念是什么?什么是类和对象
类是一个逻辑单元,包含字段、方法和属性
1.构造函数是类中的一种方法,当创建类对象时自动执行
2.字段是任何类型的变量。基本上是数据。
3.属性是在私有字段的读写方面提供帮助的成员。
4.方法是包含成堆声明i的代码块。
对象是类的示例
Q2. 什么是继承,为什么继承很重要
继承是在两个类之间创建父-子关系,其子类将自动获取父级的属性和方法。继承有利于提高代码的复用性和抽象性。
Q3. 有哪些不同类型的继承
单继承、多继承、多级继承、等级继承
Q4. 如何阻止一个类被继承
使用SEALED关键字,或者使用static关键字,但是被标记为static的类中的变量也要是static的
Q5. 什么是抽象
抽象是只显示需要的事物,隐藏它背后的细节
Q6. 什么是封装
封装的含义为将数据、方法和属性包装到一个单元
Q7. 什么是多态,它的类型是什么?
多态是指一个变量、对象或者是函数能够接受多种形式数据。比如方法重载。
多态的类型:
- Compile Time: 编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
- Run Time:运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C#中,运行时的多态性通过虚成员实现。
对于非虚方法来说,调用哪个方法取决于该实例编译时的类型。但对于虚方法来说,调用哪个方法取决于该实例运行时的类型。
虚方法是用来实现多态的,一般virtual和override一起使用
https://blog.csdn.net/weixin_43381316/article/details/108112208
- 当调用一个对象的函数时,系统会直接去检查这个对象申明定义的类,即申明类,看所调用的函数是否为虚函数;
- 如果不是虚函数,那么它就直接执行该函数。而如果有virtual关键字,也就是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是转去检查对象的实例类。
- 在这个实例类里,他会检查这个实例类的定义中是否有重新实现该虚函数(通过override关键字),如果是有,那么OK,它就不会再找了,而马上执行该实例类中的这个重新实现的函数。而如果没有的话,系统就会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。
Q8. 什么是方法重载,有多少种方法能重载
方法重载是一种多态。重载的所有方法都以不同的方式工作。
方法重载也叫编译时多态,因为编译器知道这些重名的方法能做不同的事情
Q9. Overloading 和Overriding的区别
重载和重写的区别:
重载 | 重写 |
---|---|
重载是一种多态,重载在同一个类中使用同样名称的方法,让重载的方法都以不同的方式工作。比如能够接受不同数据类型的方法。 | 重写是在不同的类中,使用相同名称和类型方法,让它以不同的方式工作。比如子类对父类方法的重写 |
重载不用使用任何关键字 | 重写需要使用virtual和override关键字 |
重载不需要继承 | 重写需要继承 |
Q10. 方法重写和方法隐藏的区别
- 方法重写有相同的名称和前面,但是在不同的类中
- 方法隐藏可以使用new关键字隐藏基类中方法的实现
1 | public class Program |
结果:
A B
1 | public class Program |
结果:
B B
Q11. 面向对象的优势和局限性
主要是对面向对象的继承、多态、封装、抽象的解释
优势:
- 通过继承提高代码的重用性
- 多态的灵活性
- 通过隐藏和封装能够提高安全性
- 容易将应用从小规模升级成大规模
- 模块化,方便纠错
局限性
- 小的应用不适合,前期设计时间开销大
面向对象和C# - 抽象类和接口
Q12. Abstract Class 和 Interface in C# .NET 抽象类和接口的区别
- 抽象类和接口的区别:
抽象类 | 接口 |
---|---|
抽象类包含方法的声明和定义 | 接口只包含方法的声明 |
抽象类使用Abstract关键字 | 接口使用Interface关键字 |
抽象类能包含方法、字段、构造器以及其他类成员 | 接口只包含方法 |
抽象类不支持多重继承 | 接口支持多次继承 |
抽象类有构造函数 | 接口没有构造函数 |
Q13. 什么时候使用抽象类或者接口
接口:你知道必须有一个方法需要放在那,但是这个方法尚不知如何实现,可以在不同的派生类中用不同的方式实现的时候就用接口。
抽象类:当你确定某些方法要被怎样具体实现的时候就用抽象类,当然也可以使用abstract关键字定义方法,并在派生类类使用override中重写。
Q14. 为什么要使用接口
因为某些业务内容可能是不确定的,但是知道大概会有那些功能。
Q15. 接口可以有构造函数吗
不行,因为构造函数是一个类被创建时自动执行的,但是接口无法被创建
Q16. 可以创建抽象类或者接口的实例吗
不行,抽象类和接口只能被继承
面向对象和C# - 通用
Q17. 什么是访问修饰符,一个类中的默认访问修饰符是什么
访问修饰符是关键字。指定类、方法的可访问性
- public
- private
- protected
- internal
- protectedinternal
Q18.什么是Boxing 和 Unboxing?
- Boxing是将值类型转换为引用类型的过程。
- Unboxing是将引用类型转换为值类型的过程。
Q19. “String” 和 “StringBuilder”的区别
字符串在C#中是不可变的。
这意味着如果您定义了一个字符串,那么您就不能修改它。每次给它赋值时,它都会创建一个新的字符串。
字符串创建器是可变的
这意味着,如果要对字符串执行任何操作,那么它就不会每次都创建一个新实例。
如果需要频繁地更改字符串,则StringBuilder是一个更好的选项,因为它不会每次都申请新内存。
Q20. C#中的基础字符串操作符
- 连接:使用 + 进行两个字符串之间的连接
- 替换:replace
- 修剪:trim() 能够修建末端的空白字符
- 包含:contains() 检查是否包含子串
Q21. 什么是可空类型
如果要保存空值,我们必须使用可空类型,因为变量类型不包含空值。
- 用法:使用
Nullable<int>
或者int?
Q22. 解释泛型,如何使用它们
泛型允许我们让类和方法类型独立或者类型安全。
使用object代替原来的类型
使用方式:
1 | public class Caculator |
或者
1 | public class Caculator<T> |
面向对象和C# - 异常处理
Q23. 如何在C#中实现异常处理
面向对象编程中的异常处理用于管理错误
- TRY:是一个代码块,其中包含可能发生错误的代码
- CATCH:当TRY块中发生任何错误时,则传递给CATCH块来处理它。
- Finally:用于执行给定一组语句,无论是否抛出异常。
- THROW:在CATCH块中,您可以使用throw关键字将堆栈跟踪传递到上一级别。
Q24. 能否执行多个Catch块
不行,我们可以编写多个catch块,但是只有一个会被执行。
Q25. Finally块是什么,什么时候用它
无论是否抛出异常都会执行的块,一般用在释放资源
Q26. 能否只包含 “Try” 块而没有 “Catch” 块
可以,但是必须要有Finally块
Q27. “throw ex” 和“throw”的区别是?
- “throw ex”:抛出异常将清空堆栈跟踪,
- “throw ”:将保存整个堆栈。
错误的做法:
1 | try |
正确的做法
1 | try |
使用“throw;”代替了“throw ex;”,后者会清空原来的堆栈跟踪信息。如果我们在抛出异常时没有指定具体的异常(简单的throw),那么它会默认地将原来捕获的异常继续上抛。这样 的话,上层代码捕获的异常还是最开始我们通过catch捕获的同一个异常。
面向对象和C# - 循环和容器
Q28. C#的循环类型
- While
- do While:跟While的区别是do,无论条件,会至少执行一次
- for
- foreach
Q29. “continue” 和 “break” 的区别?
- Continue:用于跳过某段代码回到循环的开头继续执行
- break:退出循环
Q30.Array 和 ArrayList 的区别
Array | ArrayList |
---|---|
Array 是强类型,只能存储特定类型数据 | ArrayList是弱类型,能存储任意类型数据 |
Array是固定长度 | ArrayList是可变长度 |
Q31. Arraylist 和 Hashtable的区别
Arraylist | Hashtable |
---|---|
Arraylist 添加数据只要添加值 | Hashtable添加数据时需要添加键和值 |
Q32. C#中的容器是什么,它们的类型是
C#集合旨在更有效地存储、管理和操作类似的数据。例如ArrayList、Dictionary、List、Hashtable等。
C#中的容器包括:通用容器、泛型容器、并发容器
concurrent:并发类型,C#中的线程安全集合
Q33. C# 中的IEnumerable是什么
IEnumerable是可枚举的所有非泛型集合的基接口,当我们想要在集合类之间使用Foreach,可以使用IEnumerable接口。
比如使用List迭代某个类实例化的对象
Q34. IEnumerable 和 IEnumerator 的区别
lEnumebale包含IEnumerator 功能
Q35. IEnumerable 和 IQueryable 区别,为什么在sql中使用IQueryable
IQueryable与IEnumerable 类似,用于从数据中收集sql查询。它在SYSTEM.LINQ命名空间下。
IEnumerable从数据库中获取信息会带来全部的信息再过滤,影响性能
IQueryable会先过滤再带来数据
面向对象和C# - 方法和委托
Q36. “out” 和“ref” 的区别
通过使用ref和out关键字,我们可以通过引用传递参数,当您想从一个方法中返回多个值时,您可以使用out和ref。
out | ref |
---|---|
不需要在传递out参数之前初始化它。 | 需要初始化 |
返回前必须初始化out参数 | 返回前不需要必须初始化 |
简单来说,使用out来指定一个新的值,使用ref来修改一个值。
Q37. “params” 关键字的用处
params关键字用来表示可以使用可变参数类型
当程序员对要使用的参数的数量没有任何先验知识时,比较有用
1 | public static int Add(params int[] listNumbers) |
Q38. 什么是构造函数,它的类型是什么?
构造函数是类的一种特殊方法,在创建类的实例时自动调用。构造函数的名称必须与类名相同,否则将很难从其他方法中识别出来。
C#的构造函数
- Default constructor:默认构造函数,没有任何参数的构造函数
- Parameterized constructor:参数构造函数,具有至少一个输入参数的构造函数是参数构造函数。
- Copy constructor:复制构造函数,从另一个对象复制变量
- Static constructor:静态构造函数,用于在调用类的任何静态成员之前进行调用。需要以Static作为类型
- Private constructor:私有构造函数,当构造函数是Private 修饰符时,其他类是不能从该类派生,也不可能创建该类的实例。
Q39. 什么时候使用Private constructor
单例设计模式中常使用Private constructor
私有构造函数是一个特殊的构造函数,用于只包含静态成员的类中。
Q40. C#中的Extension方法是什么,什么时候用他们?
Extension Method允许在现有类中添加新方法,而无需修改原始类的源代码。比如说使用一些原本类没有的方法。
比如说RightSubstring()
方法不是string
类中的方法,但是我们可以通过使用扩展方法来添加它。
1 | public static class StringExtensions |
Q41. 什么是Delegate? 什么时候用它们?
委托是一个变量,它保存对A函数或指向A函数的指针的引用。委托可以引用多个方法,需要具有相同的返回类型和参数。
简单来说委托就是对函数的引用。
1 | delegate void Caculator(int x, int y); |
Q42. 什么是Multicast Delegates?
多点委托对是多个函数的引用。
1 | delegate void Caculator(int x, int y); |
执行结果为:
1 | 30 |
Q43.什么是Anonymous Delegates
Anonymous Delegates,在匿名委托中,您可以创建一个委托,但是不需要声明与其关联的方法。
1 | public delegate void Caculator(int x, int y); |
Q44. Events 和 Delegates的区别
- 委托是一个变量,它保存对函数的引用或指向函数的指针。
- 事件是依赖于委托的通知机制。
事件依赖于委托,没有委托就不能被调用。事件类似于委托的包装器,以提高其安全性。
面向对象和C# - 重要关键字
this:此关键字用于引用类的当前的实例,避免了类字段和构造函数参数之间的名称混淆。
using:
使用指令
1
using System.IO;
使用语句确保即使发生异常也调用**dispose()**方法。主要用于创建数据库联系
1
2
3
4
5
6
7
8
9
10
11
12
13static void Main(string[] args)
{
using(var connection = new SqlConnection("ConnectionString"))
{
var query = "UPDATE YourTable SET Property = value";
var command = new SqlCommand(query, connection);
connection.Open();
command.ExecuteNonQuery();
//connection.Dispose();
}
}
- is 和 as 操作符:
- is: 操作符用于检查对象的类型,是一个布尔类型
- as:操作符用于在兼容的引用类型之间执行转换。比如在object和string之间进行转换,不是布尔类型
- Readonly和Constant
- Readonly:使用Readonly,可以在声明或者构造函数中赋值,初始化完成后便无法更改。ReadOnly是运行时常数
- Constant:使用Constant,只能在声明中赋值,其他地方不能更改const字段的值。Constant是编译时常数
- Static:静态类是不能被创建,不能继承的类。静态类用作静态成员,比如方法、构造函数和其他的容器
- var和 dynamic
- var:变量的类型由编译器在编译时决定。
- dynamic:变量的类型是在运行时决定的,可以在其他地方赋值其他类型的数据
- Enum:枚举是一种特殊的类,用来表示一组int类型常量,通常第一个常量由0开始