1.What is the Common Intermediate Language(CIL)
.NET 系语言被编译后的中间语言。C# class 可以派生自F# class 因为两种语言是相容的,会被编译成通用的中间语言
C# 编译器compiler并不直接将C#语言编译成二进制代码,会先将其编译成中间语言
利用反编译decompile例如IDAM 可以通过dll语言看反编译后的中间语言
JUST-IN-TIME (JIT) compiler 是CLR的典型特征 在程序运行时将CIL编译成二进制语言
2.What is CLR
The Common Language Runtime is aruntime environment that managesthe execution of .NET applications.
CLR位于应用程序和操作系统之间。CLR下执行的代码被称为托管代码(managed code)
CLR能听懂多种语言,因为这些语言都被编译成中间语言
The responsibilities of the CLR职责
- Just-in-Time compilation
- Memory management
- Exception handling
- Thread management
- Type safety and the CTS(公共类型系统)
CLR是CLI(通用语言基础设施)的实现。
编码者编码;编译器编译成CIL,编译器还准备描述所有类型(连带其中方法)的元数据;CLR管理应用所有底层low-level方面,内存管理线程异常处理等
CLR帮助开发者更多关注业务方面,而不用管内存管理等
● "What is the difference between CLR, CLI, and CIL?" CLR (Common Language Runtime) is an implementation of the CLI (Common Language Infrastructure). CIL is Common Intermediate Language, to which all .NET-compatible languages get compiled.
● "What is the CTS?" CTS is the Common Type System, which is a standardized type system for all .NET-compatible languages, which makes them interoperable- for example, we can have a C# class derived from an F# class.
● "Is the CLR the only implementation of the CIL?" No. Anyone can create their implementation of the CIL. One of the examples is Mono Runtime
3.What is the difference between C#and .NET?
Brief summary: C# is a programming language and .NET is a framework that supports applications written in C#, as well as in other .NET compatible languages.
二者关系像飞机和机场。
So what is the role of .NET?
○ It provides the execution environment called Common Language Runtime, which is responsible for things like processing the Intermediate Language, managing the memory, providing error handling, and more. 提供运行环境
○ It provides a set of standard libraries (which can be found in the System namespace)提供标准库
为什么“.NET”和“.NET Framework”也可以互换使用?
首先是 2002 年发布的 .NET Framework。事实是,人们很少使用全名,每个人都称它为“.NET”。然后,在 2016 年,.NET Core(.NET Framework 的继任者)发布。因此,在这一点上,我们有了“.NET Framework”(通常称为“.NET”)和“.NET Core”。真正的问题始于 2020 年——当时 Microsoft 发布了“.NET Core”的 5.0 版,但实际上决定从现在开始,这项技术将被称为“.NET”。因此,如今,当人们说“.NET”时,他们经常被问到“但你指的是旧的 .NET Framework 还是最新的 .NET Core?
"What is the difference between .NET and .NET Framework?"
NET is a successor of .NET Framework. .NET was originally named .NET Core, and it was renamed to .NET since version 5.0
4. What is the difference between value types and reference types?
Brief summary: The differences between value types and reference types are:
- Value types inherit from System.ValueType while reference types inherit from System.Object.
- Value types are passed by copy, reference types are passed by reference. 复制传递 引用传递
- On assignment, a variable of a value type is copied. For reference types, only a reference is copied。赋值时,值类型变量被复制。引用类型只复制引用
- All value types are sealed (which means, they cannot be inherited) 值类型不能被继承;因此value types can't have virtual or abstract members. 值类型不能具有虚拟成员或抽象成员。没有继承 就没有多态
- Value types are stored on the stack, reference types are stored on the heap (because of that, the Garbage Collector only cleans up reference types)
object 、String、 List、 Array和所有class都是引用类型
值类型只在其作用范围内有效,如一个方法体中。出了作用域,栈上的数据被清除。引用类型寻址的对象由GC在不确定的时间回收。
如果想将值类型参数值的改变对原变量产生影响,需要ref 和out。
5.What is boxing and unboxing?装箱 和 拆箱
Brief summary:
Boxing is the process of wrapping a value type into an instance of a type System.Object.
Unboxing is the opposite- the process of converting the boxed value back to a value type.
When the value is boxed, it is wrapped inside an instance of the System.Object class and stored on the heap.
boxing is done implicitly. On the other hand, the unboxing must be done explicitly by using a cast.装箱隐式转换,拆箱需要强制类型转换
Unboxing unwraps the original value from the object and assigns it to a value type variable.
The unboxing requires the exact type match. 拆箱需要精确的类型匹配 我们可以把一个short变量赋值给int变量,但是如果把装箱了的short拆成int会报错。
Please be aware that boxing and unboxing come with a performance penalty. Unlike regular variables assignment, boxing requires the creation of a new object and allocating memory on the heap for it. The unboxing requires a cast, which is also computationally expensive. 请注意,装箱和拆箱会造成性能损失。与常规变量赋值不同,装箱需要创建一个新对象,并在堆上为其分配内存。拆箱需要强制转换,这在计算上也很昂贵。
装箱和拆箱有什么用?
boxing and unboxing are necessary for providing a unified type system- that is, that we can treat any variable in C# as an object. Without boxing and unboxing, we couldn't have the ultimately generic code that accepts any type of variable- we would have to distinguish value and reference types and possibly provide separate implementations for both of them.装箱和拆箱对于提供统一的类型系统是必要的——也就是说,我们可以将 C# 中的任何变量视为一个对象。如果没有装箱和拆箱,我们就无法拥有接受任何类型的变量的最终通用代码——我们必须区分值和引用类型,并可能为它们提供单独的实现。这在有泛型和ArrayList这样的类之前很有用,现在也仍在使用。
for example in ADO.NET which is used to store objects in databases- at some point, this framework treats every piece of data as an object. Without boxing, it wouldn't be able to handle value types
6. Three main type of errors
编译错误,也就是句法syntax错误 最常见,IDE会报错,有提示,容易解决
运行错误 需要debugger在错误前停止
逻辑错误 确保应用程序中不存在逻辑错误的最佳方法是创建一套可靠的单元测试。
●"What type of errors do unit tests protect us from?" Both runtime errors and logical errors. 单元测试可以保护单元测试能免除什么类型的错误?”运行时错误和逻辑错误。
● "What's the C#'s mechanism for handling runtime errors?" Exceptions- they are used for handling runtime errors. “C# 处理运行时错误的机制是什么?”异常 - 它们用于处理运行时错误。
7.How are exceptions handle in C#?
Exceptions are handled by try-catch-finally blocks. Try contains code that may throw exceptions, catch defines what should be done if an exception of a given type is thrown, and finally is executed no matter if the exception was thrown or not
错误分类:
系统错误: 超出内存
数值错误:溢出
语法错误:类型转换
操作错误:移除空列表的元素
多个catch的时候,将catch更具体异常的catch块放前面,更通用的放后面,优先按照更具体地catch来执行。
finally常用于手动清除资源,比如try中连接数据库出现异常,需要关闭连接;等待垃圾收集器需要很长时间
异常地基类型 System.Exception
8.What are the types of access modifiers in C#?
命名空间层级 2个
public internal
类(struct record)层级 6个
public 任何程序集
internal 本程序集
protected 子类
本程序集看后面
protected internal 本程序集内和internal一样,本程序集外加上本程序之外的子类
private protected 本程序集内和protected一样 本程序集外和private一样
private 仅仅类的内部
9.What are the default access modifiers in C#?默认访问修饰符
the most restrictive access modifier that is valid in the given context最严格
命名空间层级 internal
类层级 private 包括内部类
面试题:类的默认访问修饰符 按照普通类和内部类分别回答0
10.What is the purpose of the "sealed" modifier?
可以修饰类,防止被继承
对于方法可以修饰重写方法,防止继续被重写
不可以修饰抽象类,抽象类就是用来被继承的
缺点:有时候用户希望自定义逻辑;mock难以使用,mock常用于单元测试
11. What is the purpose of the "params" keyword?
params 允许将同类型的任意个数的参数传进方法
一维数组
一定要把params修饰的变量防止参数列表的最后一个,不然编译器不知道参数是否属于参数数组
What is the difference between a class and a struct?类和结构体的区别
Brief summary:
- Structs are value types and classes are reference types.
- Structs can only have a constructor with parameters, and all the struct's fields must be assigned in this constructor.只能有一个带参构造器 所有的字段必须在这个构造器里赋值
- Structs can't have explicit parameterless constructors.不能有显示无参构造器
- Structs can't have destructors.没有析构函数
23 ==操作符和equals方法的区别
对于引用类型: ==操作符比较引用值;equals方法默认比较引用值,但是常用自定义将其重写为比较内容。
对于值类型(如结构体):不支持==操作符;equals方法默认比较内容,也可以重写它。
24 deep copy 和shallow copy深拷贝和浅拷贝
浅拷贝:拷贝值类型成员和引用类型成员的引用 MemberwiseClone()方法:创造一个浅拷贝对象
深拷贝:拷贝值类型成员和引用类型成员 会新建对象 引用不会被拷贝 而是变成新的对象的引用
使用场景:deep copy适合需要自己修改对象而不对原对象产生影响的时候使用。
29 What is the difierence with the const and the readonly modifiers
const:编译时被赋值;可以是数字,布尔类型, 字符串, 空引用;不能被static修饰,因为本身就是隐式的static的
readonly:运行时在构造器中被赋值;可以是任何类型;可以被static
const keyword. It is used to declare a variable whose value is not supposed to change. The exact value must be known at compile time.比如一周七天,字节=8bit, float PI=3.14f
Readonly means the value will not be reassigned after it has been assigned for the first time. That may seem similar to the const, but there is a difference- the readonly values do not need to be known at the compile time, they can be a result of somecalculation or user input. We use readonlys anywhere where we want the value to never change after it was first set. The readonly member doesn't have to be assigned at declaration- unlike const, it can be assigned via the constructor。
Tip: other interview questions on this topic:
● "Assume you need the PI number in your program. How would you define it?"
It is a bit tricky because the best answer is "I would not, I would use Math.PI that is already defined in C#". But if for some reason it would not be present, I would define it in some static class MathConsts as a const value.
● "How can you prevent the field from being modified after it is set up in the constructor?"
By making it readonly.
● "When do you use const, and when do you use readonly?" I would use const when the value is known at the compile time, for example, mathematical constants like PI number should be const. I would use readonly when the value is known at runtime, but I do not wish it to change after it is assigned
个人总结:const用来定义一些永恒不变的值(编译时就知道了),readonly定义一些可以首次赋值时自由赋值之后不再改变的变量。
31 interface and abstract class
抽象类(定义子类是什么):
- 可以包含方法实现和成员变量。
- 使用关键字
abstract定义。 - 适用于需要提供共享代码和声明的场景(比如动物和具体的动物)。
- 一个类只能继承抽象类
- 无法创造抽象类实例
接口(定义了实现类要做什么):
- 只包含方法、属性、事件和索引器的声明(不能有字段、构造函数、方法的实现)。
- 使用关键字
interface定义。 - 适用于需要定义一组不相关类实现的契约的场景()
- 一个类可以实现多个接口
为什么接口不能有构造函数?
接口的设计意图是为了描述对象的能力,而不是它们的实现方式或状态。构造函数涉及到对象的状态初始化,这是实现的具体细节。因此,接口不适合包含构造函数。接口用于定义行为契约,而不涉及实现细节和对象状态的初始化。实现接口的类负责定义和实现构造函数,以初始化对象的状态。
为什么接口有属性?
接口中的属性实际上是方法的集合:get 访问器和 set 访问器。因此,当你在接口中定义属性时,实际上是定义了必须实现的访问器方法。
C#8后接口可以提供一个默认的方法实现,可以带方法体
抽象类可以包含抽象方法,但这不是强制性的,可以只有具体方法;但包含抽象方法的类一定是抽象类。
32 polymorphism 多态
多态性 使得相同的方法调用在不同的对象上表现出不同的行为。包括接口 抽象类型 继承 虚方法 泛型