Bootstrap

C# 面试题

C# 面试题
1. CTS CLS CLR 分别作何解释
CTS :通用语言系统。 CLS :通用语言规范。 CLR :公共语言运行库。
CTS Common Type System 通用类型系统。 Int32 Int16 int String string
Boolean bool
每种语言都定义了自己的类型, .NET 通过 CTS 提供了公共的类型,然后翻译生成对应的 .NET
型。
CLS Common Language Specification 通用语言规范。不同语言语法的不同。每种语言都有自
己的语法, .NET 通过 CLS 提供了公共的语法,然后不同语言翻译生成对应的 .NET 语法。
CLR Common Language Runtime 公共语言运行时,就是 GC JIT 等这些。有不同的 CLR
比如服务器
CLR Linux CLR Mono )、 Silverlight CLR(CoreCLR) 。相当于一个发动机,负责执行 IL
2. 什么是类
类是创建对象的模板。它包含属性和方法。我们可以从一个类创建许多对象实例
3. 面向对象编程的主要概念是什么?
封装、抽象、多态和继承是面向对象编程的主要概念。准备好描述其中的每一个。面向对象编程与
过程编程的不同之处在于过程编程按时间顺序、逐步进行,而面向对象编程则灵活得多。
4. 什么是对象?
对象是一个类的实例,我们通过它访问该类的功能。我们可以使用 “new” 关键字来创建一个对象。
在内存中创建对象的类保存有关该类的函数、数据成员和行为的信息。
5. 什么是构造函数,它有哪些不同的类型?
造函数就像一个与类同名的方法,但它是唯一的方法。即使没有创建,编译器也会在创建类的对象
时在内存中创建一个默认构造函数。构造函数用于使用一些默认值初始化对象。默认构造函数、参
数化构造函数、复制构造函数、静态构造函数和私有构造函数都是不同的构造函数类型。
6. C# 中的析构函数是什么?
析构函数清除内存以释放资源,并由垃圾收集器自动管理。
7. C# 代码是托管代码还是非托管代码?
C# 是托管代码,因为公共语言运行时将代码编译为中间语言代码。 C++ 将提供非托管代码的示
例。托管代码只是指其执行由运行时管理的代码。
8. 什么是值类型和引用类型?
我们可以将变量分为值类型和引用类型。值类型变量直接包含值,而引用类型变量包含内存地址的
引用,其中值实际存储在内存中。 Bool byte int char decimal 是值类型。字符串、类、委
托都是引用类型。
9. 什么是命名空间,它是强制性的吗?
命名空间是一种以相同名称组织相同组或功能的类的方法。我们可以称它为模块。尽管将类放在命
名空间中并不是强制性的。
10. 用例子解释 C# 中的注释类型。
C# 中有三种类型的注释。
单行注释 多行注释
XML 注释
单行注释的示例是: // 嘿,这是单行注释
多行注释的一个例子是: / 这是一个多行注释写成两行 /
XML 注释的一个示例是: /// 概括 /// 这里可以写任何东西 /// 概括
11. 请解释封装。
封装是将函数和数据成员包装在一个类中的过程;它就像一个胶囊,一个单一的单元。封装可防止
来自函数外部的未经授权或不需要的数据更改。它用于更好地控制和标准化的代码。
12. 什么是抽象?
抽象是只暴露类的必需特性并隐藏不必要信息的方法。我们可以尝试以摩托车为例来理解它:骑手
知道自行车的颜色、名称和型号。尽管如此,他们仍然不了解内部发动机和排气功能。同样,抽象
侧重于提供对特定功能的访问,而不暴露该功能在内部是如何工作的。
13. 什么是多态性?
多态意味着相同的方法但不同的实现。有两种类型的多态性。
编译时多态性 是通过方法重载实现的
运行时多态性 是通过方法覆盖来实现的
14. 什么是继承?
一个类可以从另一个类(称为其父类)继承数据成员和方法。继承属性和方法的类将被称为子类、
派生类。派生类中的某些属性可以被覆盖。从类继承特征的能力使管理类的整个过程变得更加容
易,因为你可以创建自定义的子类。原始类将被称为父类或基类。
15. 如何在同一个类中实现多个具有相同方法名的接口?
要实现具有相同方法名称的多个接口,你将避免在函数体中实现。相反,你将显式地将接口名称提
供给方法的主体。编译器将了解所引用的接口方法,从而解决问题。
16. 什么是虚方法,它与抽象方法有什么不同?
一个虚方法必须有一个默认实现,我们可以在派生类中使用 override 关键字来覆盖这个虚方法。
抽象方法没有实现,只在抽象类内部创建。在抽象类的情况下,从抽象类派生的类必须具有该抽象
方法的实现。
17. 什么是方法重载和方法覆盖?
方法重载和覆盖都是一种多态性。
方法重载是指我们有一个名称相同但签名不同的函数。
方法覆盖是当我们使用 override 关键字覆盖子类中基类的虚拟方法时。
18. 什么是 static 关键字?
我们使用 static 关键字来创建静态类、静态方法或静态属性。当我们创建一个静态类时,该类中只
能有静态数据成员和静态方法。静态意味着我们不能创建该类的实例。该类可以像
ClassName.methodName 一样直接使用。
当需要其他类的所有实例都具有的特殊功能时,我们使用静态类。例如,需要加载一些默认的应用
程序级值。我们创建一个带有静态函数的静态类。然后,所有其他类都可以访问该类,而无需创建
任何实例。它还与所有类共享相同的数据。
19. 我们可以在静态类中使用 “this” 吗?
不。 “this” 不能与静态类一起使用,因为我们只能在静态类中使用静态变量和静态方法。
20. 常量和只读变量有什么区别?
有几点不同: 常量变量只能在声明时赋值,我们不能在整个程序中更改该变量的值。
我们可以在声明时或在同一类的构造函数中将值分配给只读变量。
21. C# 中的 string string builder 有什么区别?
string 是不可变的对象。当我们必须执行一些操作来更改字符串或附加新字符串时,它会清除字符
串对象的旧值,并在内存中创建一个新实例以将新值保存在字符串对象中。
StringBuilder 是一个可变对象,这意味着它每次都会为添加字符串(追加),替换字符串(替
换)等操作创建一个新实例。它仅将旧对象用于对字符串执行的任何操作,从而提高性能。
22. 解释 “continue” “break” 语句。
我们可以在 C# 的循环中使用 continue break 语句。使用 break 语句,我们可以中断循环执
行,而使用 continue 语句,我们可以中断循环的一次迭代。
23. 什么是装箱和拆箱?
值类型数据类型到引用类型(对象)数据类型的转换称为装箱
拆箱是将引用类型数据类型转换为值类型
24. 什么是密封类?
我们使用 “sealed” 关键字来创建一个密封类。当不需要进一步继承或需要限制该类被继承时,类被
创建为密封类。
25. 什么是枚举?
枚举 关键字在许多语言中都很常见。枚举是一种值。它用作相关常量的集合,称为枚举列表。 枚
举可以是 int float double byte 。但如果它不是 int ,则需要显式转换。 .NET 框架枚举可用于
创建数字常量。 Int 是枚举元素的默认值。默认情况下,第一个枚举数的值为 0 ,并且每个后续的
枚举数都增加 1 ,就像一个数组一样。请参考以下语法: enum Day { Sat, Sun, Mon, Tue, Wed,
Thu, Fri };
26. 请解释 “using” 语句。
关键字 “using” 用于定义该 using 语句块中使用的资源的范围。一旦代码块完成执行,在 using 代码
块中使用的所有资源都会被释放。
27. 什么是访问修饰符?解释每种类型。
访问修饰符是用于提供对类、成员或函数的可访问性的关键字。以下是它的类型:
Public 可以在任何地方访问,没有任何限制
Protected 访问仅限于继承该类的类
Internal 只能在当前程序集中访问
Private 外部无法访问
28. int? int 有什么区别
int ?为可空类型,默认值可以是 null
int 默认值是 0
int? 是通过 int 装箱为引用类型实现
29. C# 中参数传递 ref out 的区别?
1 ref 指定的参数在函数调用时必须先初始化,而 out 不用
2 out 指定的参数在进入函数时会清空自己,因此必须在函数内部进行初始化赋值操作,而
ref 不用
总结: ref 可以把值传到方法里,也可以把值传到方法外; out 只可以把值传到方法外
注意: string 作为特殊的引用类型,其操作是与值类型看齐的,若要将方法内对形参赋值后的结果
传递出来,需要加上 ref out 关键字。 30. 什么是 C# 委托?
委托就像函数指针,它是一个引用数据类型,保存着方法的引用。我们使用委托来编写泛型类型安
全函数。所有委托都派生自 System.Delegate 。可以使用 delegate 关键字后跟函数签名来声明委
托,如下所示。这些是代表的特征:
委托派生自 System.Delegate
代表具有签名和返回类型。分配给代表的函数必须符合此签名
代表可以指向实例方法或静态
委托对象一旦创建,就可以在运行时动态调用它所指向的方法
委托可以同步和异步调用方法
31. 委托有哪些不同类型?
代表分为三种类型:
单个委托 可以调用单个方法
多个委托 可以调用多个方法。委托方法可以进行多播。我们可以使用 + 运算符在委托实例中
添加一个方法,也可以使用 - 运算符删除一个方法。所有方法在分配时按顺序调用。
.Net Framework 3.5 引入了 通用委托。 无需在通用委托中创建实例。
32. 什么是数组?
该数组存储相同类型的值。它是将变量存储到内存位置的集合
33. System.Array.CopyTo() System.Array.Clone() 有什么区别?
使用 Clone() 方法,我们可以使用 CopyTo() 方法创建一个包含原始数组的所有元素的新数组对
象。现有数组的所有项目都复制到另一个现有数组中。两种方式都会创建一个浅拷贝。
34. Array ArrayList 有什么区别?
Array ArrayList 类似。当你想存储相同类型的项目时,可以使用 Array Array 具有固定大小。当
你要存储任何类型的数据时,我们使用 ArrayList ArrayList 没有固定大小。
35. 什么是 C# 中的交错数组?
交错数组就像一个嵌套数组,其中交错数组的每个元素本身就是一个数组。锯齿状数组的项目可以
具有不同的维度和大小。锯齿状数组是 C# 中引入的一种特殊类型的数组。锯齿状数组是数组的数
组,其中每个数组索引的长度可以不同。
36. struct class 有什么区别?
类和结构体都是用户定义的,但有很大的不同。 struct 继承自 System.Value 类型,因此它是值类
型。当数据量较小时,结构体更可取。结构不能是抽象的。无需使用 new 关键字创建对象。 Struct
无权创建任何默认构造函数。
37. “throw” “throw ex” 有什么区别?
“throw” 语句将保留前一个函数的原始错误堆栈,而 “throw ex” 语句将保留从抛出点开始的堆栈跟
踪。通常,建议使用 “throw” ,因为它提供了准确的错误信息和跟踪数据。
38. 解释 var dynamic
我们可以声明变量的 var 类型,而无需明确指定 .net 数据类型。编译器在编译时根据分配给它的值
自动检测变量的类型。我们不能声明一个 var 类型的变量而不给它赋值。 var 类型变量的值不能在
后面的代码中更改。动态与 var 相反。
稍后我们可以在代码中更改动态类型变量的值。它还根据分配给它的值决定变量的类型。 就像在创
建动态类型的变量时,会为其分配一个整数类型的值,然后在进一步的代码中,我们可以为该变量
分配一个字符串类型的值。它保存最后更改的值,其行为类似于它保存的最新值的数据类型。
39. 什么是多线程,它有哪些不同的状态? C# 中的任何代码块都在称为线程的进程中运行。线程是程序的执行路径。简单的应用程序可以在
单线程上运行,但今天的程序经常使用多线程。多线程将进程的执行划分为多个线程以同时执行
它,从而提高效率。 通过多线程,我们可以一次运行多个任务。程序更高效、更快捷。但是我们还
需要了解线程是如何工作的。每个线程都有自己的生命周期,其中包括线程的各种状态:
未启动状态: 在这种状态下,编译器创建线程的实例但等待启动方法。
已启动: 是线程准备好运行并等待 CPU 周期时的状态。
不可运行状态: 线程在以下情况下不可执行。
当我们调用 睡眠 等待 方法时。
I/O 操作阻塞线程。
40. C# 中的异常处理是如何完成的?
异常处理通过 try catch finally throw 模型进行管理。这些是整个模型中使用的关键字。下面
是每个关键字的解释:
Try 我们将代码保存在我们想要处理异常的 try 块中。
Catch try 块中发生任何异常时,在异常处理程序的帮助下将其捕获到 catch 块中。
finally 为了不考虑错误地执行代码块,我们将该代码放在 finally 块中以执行。
Throw 发生问题时抛出异常。
41. 什么是序列化?
当我们想通过网络发送一个对象时,我们必须将该对象转换为字节流。序列化是将对象转换为字节
流的过程。为了便于对象进行可序列化,它应该实现 ISerialize 接口。反序列化的过程是从字节流
创建对象的逆过程。
42. C# 中的泛型是什么?
C# 中的泛型:
提高性能。
增加类型安全。
减少重复代码。
制作可重用的代码。
使用泛型,我们可以创建集合类。最好使用 System.Collections.Generic 命名空间而不是
System.Collections 命名空间中的类(例如 ArrayList )来创建泛型集合。
43. 什么是反射( Reflection )?
Reflection C# 中的一个特定类,用于访问程序集或类的元数据。可以使用反射检索以下信息:
Assembly name
Class name
Method name
Object type
It Identifies properties and methods.
44. 什么是特性是?
特性与属性是完全不相同的两个概念,只是在名称上比较相近。 Attribute 特性就是关联了一个目
标对象的一段配置信息,本质上是一个类,其为目标元素提供关联附加信息,这段附加信息存储在
dll 内的元数据,它本身没什么意义。运行期以反射的方式来获取附加信息
一种边界,它由公共语言运行库围绕同一应用程序范围内创建的对象建立(即,从应用程序入口点
开始,沿着对象激活的序列的任何位置)。
应用程序域有助于将在一个应用程序中创建的对象与在其他应用程序中创建的对象隔离,以使运行
时行 为可以预知。 在一个单独的进程中可以存在多个应用程序域。应用程序域可以理解为一种轻量级进程。起到安全
的作用。占用资源小。
45. 什么是不可变字符串?
不可变字符串是不能更改的对象,尽管你可以更改对它的引用。通常,只要你有绝对不应该更改的
常量,就应该使用不可变字符串。但是,你应该谨慎使用此技巧,因为如果你稍后尝试更改不可变
字符串,它可能会引发错误。
46. C #中, string str = null string str = “” 的区别
string str = null 是不给他分配内存空间 , string str = "" 给它分配长度为空字符串的内存空间
;