参考资料:

 

显式接口实现 - C# 编程指南 - C# | Microsoft Learn

 C#中List的动态扩容机制_c# list 扩容-CSDN博客


C#中List的动态扩容机制_c# list 扩容-CSDN博客

有两个接口IA和IB,他们中有一个同名方法Test()
一个类同时继承这两个接口,应该如何处理他们的同名方法?

可以显示实现接口

(显示实现接口:显式接口实现 - C# 编程指南 - C# | Microsoft Learn,注意:显式接口实现没有访问修饰符,因为它不能作为其定义类型的成员进行访问。可以为在接口中声明的成员定义一个实现。 如果类从接口继承方法实现,则只能通过接口类型的引用访问该方法。 继承的成员不会显示为公共接口的一部分。)


IA.Test()
IB.Test()

委托和事件在使用上的区别是什么?

事件相对委托来说,事件在外部使用时只能 +=、-=

  • 大致来说,委托是一个类,该类内部维护着一个字段,指向一个方法。事件可以被看作一个委托类型的变量,通过事件注册、取消多个委托或方法。
  • 委托可以用 “=” 来赋值,事件不可以。
  • 委托可以在声明它的类外部进行调用,而事件只能在类的内部进行调用。
  • 委托是一个类型,事件修饰的是一个对象。
  • 委托就是一个类,也可以实例化,通过委托的构造函数来把方法赋值给委托实例
  • 触发委托有 2 种方式:委托实例.Invoke (参数列表),委托实例 (参数列表)
    事件可以看作是一个委托类型的变量
    通过 += 为事件注册多个委托实例或多个方法
    通过 -= 为事件注销多个委托实例或多个方法
    例如,EventHandler 就是一个委托

C#中的List是如何扩容的

List的本质是数组

详细可以参考:C#中List的动态扩容机制_c# list 扩容-CSDN博客

接口 Interface 与抽象类

抽象类
当 2 个或多个类中有重复部分的时候,我们可以抽象出来一个基类,如果希望这个基类不能被实例化,就可以把这个基类设计成抽象类。
当需要为一些类提供公共的实现代码时,应优先考虑抽象类。因为抽象类中的非抽象方法可以被子类继承下来,使实现功能的代码更简单。

接口
当注重代码的扩展性跟可维护性时,应当优先采用接口。
接口与实现它的类之间可以不存在任何层次关系,接口可以实现毫不相关类的相同行为,比抽象类的使用更加方便灵活;
接口只关心对象之间的交互的方法,而不关心对象所对应的具体类。接口是程序之间的一个协议,比抽象类的使用更安全、清晰。一般使用接口的情况更多。

区别:

接口不是类(无构造函数和析构函数),不能被实例化,抽象类可以间接实例化(可以被继承,有构造函数,可以实例化子类的同时间接实例化抽象类这个父类)。

接口只能做方法申明,抽象类中既可以做方法申明,也可以做方法实现。

抽象类中可以有实现成员,接口只能包含抽象成员。因此接口是完全抽象,抽象类是部分抽象。抽象类要被子类继承,接口要被类实现。

抽象类中所有的成员修饰符都能使用,接口中的成员都是对外的,所以不需要修饰符修饰。

接口可以实现多继承,抽象类只能实现单继承,一个类只能继承一个类但可以实现多个接口。(抽象方法要被实现,所以不能是静态的,也不能是私有的。)

C# 和 C++ 的区别?

C# 与 C++ 比较的话,最重要的特性 就是 C# 是一种完全面向对象的语言,而 C++ 不是,另外 C# 是基于 IL 中间语言和.NET Framework CLR 的,在可移植性,可维护性和强壮性都比 C++ 有很大的改进。C# 的设计目标是用来开发快速稳定可扩展的应用程序, 当然也可以通过 Interop 和 Pinvoke 完成一些底层操作

  • 具体对比:
    • 继承:C++ 支持多继承,C# 类只能继承一个基类中的实现但可以实现多个接口。
    • 数组:声明 C# 数组和声明 C++ 数组的语法不同。在 C# 中,“[]” 标记出现在数组类型的后面。
    • 数据类型:在 C++ 中 bool 类可以与整型转换,但 C# 中 bool 类型和其他类型(特别是 int)之间没有转换。long 类型:在 C# 中,long 数据类型为 64 位,而在 C++ 中为 32 位。
    • struct 类型:在 C# 中,类和结构在语义上不同。struct 是值类型,而 class 是引用类型。
    • switch 语句:与 C++ 中的 switch 语句不同,C# 不支持从一个 case 标签贯穿到另一个 case 标签。
    • delegate 类型:委托与 C++ 中的函数指针基本相似,但前者具有类型安全,是安全的。
      从派生类调用重写基类成员。 base 使用 new 修饰符显式隐藏继承成员。
      重写方法需要父类方法中用 virtual 声名,子类方法用 override 关键字。
      预处理器指令用于条件编译。C# 中不使用头文件。 C# 预处理器指令
    • 异常处理:C# 中引入了 finally 语句,这是 C++ 没有的。
    • C# 运算符:C# 支持其他运算符,如 is 和 typeof。它还引入了某些逻辑运算符的不同功能。
    • static 的使用,static 方法只能由类名调用,改变 static 变量。
  • 在构造基类上替代 C++ 初始化列表的方法。
    • Main 方法和 C++ 及 Java 中的 main 函数的声明方式不同,Main 而不能用 main
    • 方法参数:C# 支持 ref 和 out 参数,这两个参数取代指针通过引用传递参数。
    • 在 C# 中只能在 unsafe 不安全模式下才使用指针。
    • 在 C# 中以不同的方式执行重载运算符。
    • 字符串:C# 字符串不同于 C++ 字符串。
    • foreach:C# 從 VB 中引入了 foreach 关键字使得以循环访问数组和集合。
    • C# 中没有全局方法和全局变量:方法和变量必须包含在类型声明(如 class 或 struct)中。
    • C# 中没有头文件和 #include 指令:using 指令用于引用其他未完全限定类型名的命名空间中的类型。
    • C# 中的局部变量在初始化前不能使用。

装箱和拆箱是指什么?

装箱是将值类型转换为引用类型,把栈中内容迁移到堆中去,值类型数据拷贝到新的内存堆中
栈中分配一个新的引用地址指向内存堆

拆箱是将引用类型转换为值类型,把堆中内容迁移到栈中去,将该值数据复制到栈中的值类型

反射的实现原理?

  • 可以在加载程序运行时,动态获取和加载程序集,并且可以获取到程序集的信息反射即在运行期动态获取类、对象、方法、对象数据等的一种重要手段。
    主要使用的类库:System.Reflection
  • 核心类:
    • Assembly 描述了程序集
    • Type 描述了类这种类型
    • ConstructorInfo 描述了构造函数
    • MethodInfo 描述了所有的方法
    • FieldInfo 描述了类的字段
    • PropertyInfo 描述类的属性

通过以上核心类可在运行时动态获取程序集中的类,并执行类构造产生类对象,动态获取对象的字段或属性值,更可以动态执行类方法和实例方法等。
审查元数据并收集关于它的类型信息的能力。

更多推荐