当前位置: 首页 > news >正文

C#八股总结

重载和重写的区别

方法重载:在同一个类中定义多个同名但参数不同的方法。
方法重写:通过使用 virtual 和 override 关键字,实现基类和派生类之间的方法重写。
重载发生在同类中,重写发生在父子类中
重载方法名相同参数不同,重写方法名和参数列表都相同

面向对象的三大特点

封装,继承,多态
继承能够提高代码重用度,增强可维护性。继承最主要的作用就是把子类的公共属性集合起来,便于共同管理,使用起来更加方便
继承的传递性:b继承a,c继承b,c也有a的特性
继承的单根性:C#中一个类只能继承一个类,不能有多个父类
继承是实现多态的重要手段,通过基类引用指向派生类对象,可以实现动态绑定。

封装是将数据(属性)和操作数据的方法(行为)相结合,并限制外部直接访问数据的能力。保护对象的内部状态,同时提供公共方法让外部访问,增强数据的安全性(private,public修饰符)

多态性:通过统一的接口来调用不同类的对象,从而实现统一操作有不同的表现形式。两种主要形式为重载和重写

值类型和引用类型的区别

值类型、引用类型是根据数据存储的⻆度来分的)就是值类型用于存储数据的值,引用类型用于存储对实际数据的引用。
值类型包含了所有简单类型(bool,char,int,float,enum,struct),继承自基类System.ValueType
引用类型包含了string,object,class,interface,delegate,继承自基类System.Object
1.值类型变量直接把变量的值保存在堆栈中,引⽤类型的变量把实际数据的地址保存在堆栈中。
2.值存取快,引用类型存取慢
3.值类型表示实际数据,引用类型表示储存在内存堆中的数据的指针和引用
4.值类型的变量直接存放实际的数据,引用类型的变量存放的是数据的地址,即对象的引用

private,public,protected的区别

public:对任何类和成员都公开,无限制访问
private:仅对该类公开
protected:对该类及其派生类公开

ArrayList和List的主要区别

ArrayList 是非泛型集合,存储的数据类型为 object。他可以存储任何类型的对象,但在使用时需要进行类型转换(装箱和拆箱),可能导致运行时错误。
由于需要进行装箱和拆箱,ArrayList 在处理值类型时性能较低。此外,由于其对每个元素都必须进行类型检查,因此在性能上也劣于 List。

List:
List 是泛型集合,提供类型参数 T,确保在编译时就能检查类型,避免了类型转换问题。因此,它更安全且性能更高。
List 提供更好的性能,因为它不需要进行装箱和拆箱,且能够直接操作指定的类型。

GC(垃圾回收)产生的原因,如何避免?

为了避免内存溢出而产生的回收机制
如何避免:
减少new产生对象的次数
使用公共的的对象(静态成员)
将String转换为StringBuilder

interface和抽象类之间的不同

接口是一种完全抽象的类型,定义了一组方法、属性、事件或索引器,但不提供任何实现。
抽象类是一种包含部分实现的类,可以包含抽象方法(没有实现)和具体方法(有实现)。

接口用于定义一组功能,这些功能可以被多个类实现。通过接口,可以确保不同的类具有一致的功能契约。
抽象类用于提供一个基础类,允许子类继承并重用代码,同时也强制子类实现特定的方法。

接口可以多继承,抽象类是单继承(一个类只能继承自一个抽象类)

接口中的成员默认都是 public,不能使用其他访问修饰符(如 private 或 protected)。
抽象类中的成员可以有多种访问修饰符(如 public、protected、private),提供了更灵活的访问控制。

关键字Sealed用在类声明和函数声明时的作用

类声明时可防止其他类继承此类,在方法中声明则可防止派生类重写此方法。

反射的实现原理

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

在类的构造函数前加上static会报什么错?为什么?

C# 中有静态构造函数,使用 static 修饰符定义,用于初始化类的静态成员。静态构造函数在类被加载到内存中时执行,且只执行一次,而不是在创建类的实例时执行。因此,静态构造函数与常规构造函数的目的和用法是不同的。

静态成员(变量和方法)属于类本身,而不是类的实例。
可以通过类名直接访问静态成员,无需创建对象。

C#中常见的容器类

Stack:先进后出,入栈和出栈,底层泛型数组实现,入栈动态扩容二倍
Queue:先进先出,入队和出队,底层泛型数组实现,表头表尾指针,判空通过size比较
Array数组:需要声明长度,不安全
ArrayList数组列表:动态增加数组,不安全,实现了IList接口,Object数组实现
List列表:底层是泛型数组,动态扩容(将泛型数据存储在一个泛型数组中,添加元素时若超过当前泛型数组容量则二倍扩容,实现List大小动态可变
LinkList链表:底层由链表实现,数组插入删除效率高,且不用动态扩容数组

C#中常规容器和泛型容器有什么区别

不带泛型的容器需要装箱拆箱操作速度慢。泛型容器更高效更安全

常见的数值类

简单值类型:int类型,bool类型,char类型
复合值类型:结构类型,枚举类型

C#中委托 和 接口有什么区别?各用在什么场合?

委托用于表示对一个或多个方法的引用,使得可以将方法作为参数传递或进行回调操作。它常用于事件处理和异步编程,以便在特定条件下调用指定的方法。更侧重于方法的调用和执行,适用于事件和回调场景。
接口则关注类的行为和功能定义,适用于需要实现契约、增强系统灵活性和可维护性的情况。类通过实现接口来遵循一定的契约,这种设计促进了代码的解耦合和可扩展性。接口支持多重继承,可以让不同的类以相同的方式响应某些操作,从而实现多态。

C#中unsafe关键字是用来做什么的?什么场合下使用?

非托管代码才需要这个关键字,一般用在带指针操作的场合。
项目背包系统的任务装备栏使用到

C#中ref和out关键字有什么区别?

ref修饰引用参数。参数必须赋值,带回返回值,又进又出

out修饰输出参数。参数可以不赋值,带回返回值之前必须明确赋值,

引用参数和输出参数不会创建新的存储位置

如果ref参数是值类型,原先的值类型数据,会随着方法里的数据改变而改变,

如果ref参数值引用类型,方法里重新赋值后,原对象堆中数据会改变,如果对引用类型再次创建新对象并赋值给ref参数,引用地址会重新指向新对象堆数据。方法结束后形参和新对象都会消失。实参还是指向原始对象,值不够数据改变了

For,foreach,Enumerator.MoveNext的使用,与内存消耗情况

for循环可以通过索引依次进行遍历,foreach和Enumerator.MoveNext通过迭代的方式进行遍历。
内存消耗上本质上并没有太大的区别。
但是在Unity中的Update中,一般不推荐使用foreach 因为会遗留内存垃圾。

函数中多次使用string的+=处理,会产生大量内存垃圾(垃圾碎片),有什么好的方法可以解决。

通过StringBuilder那进行append,这样可以减少内存垃圾

当需要频繁创建使用某个对象时,有什么好的程序设计方案来节省内存?

设计单例模式进行创建对象或者使用对象池

Foreach循环迭代时,若把其中的某个元素删除,程序报错,怎么找到那个元素?以及具体怎么处理这种情况?(注:Try…Catch捕捉异常,发送信息不可行)

foreach不能进行元素的删除,因为迭代器会锁定迭代的集合,解决方法:记录找到索引或者key值,迭代结束后再进行删除。

GameObject a=new GameObject() GameObject b=a 实例化出来了A,将A赋给B,现在将B删除,问A还存在吗?

存在,b删除只是将它在栈中的内存删除,而A对象本身是在堆中,所以A还存在

C#中委托和事件的区别

委托就是用来存储方法的引用,让你可以方便地调用这些方法。你可以把一个方法“放进”委托中,并在需要的时候通过这个委托来“呼叫”它。这使得代码更加灵活,因为你可以根据需要选择不同的方法来执行。

事件就是一种机制,用来让对象之间互相通知。当某个事情发生了(比如一个按钮被点击),你可以触发这个事件,已注册的处理程序都会收到通知,并可以做出相应的反应。

  • 触发委托有两种方式:委托实例Invoke(参数列表),委托实例(参数列表)
  • 通过+=为事件注册多个委托实例或多个方法
  • 通过-=为事件注销多个委托实例或多个方法
  • EventHandler就是一个委托

结构体和类有何区别

结构体是一种值类型,而类是引用类型
结构体是当成值来使用的,类则通过引用对实际数据操作

C#的委托是什么?有何用处

委托类似于一种安全的指针引用,在使用它时时当作类看待而不是一个方法,相当于对一组方法的列表的引用
用处:使用委托使程序员可以将方法引用封装在委托对象内,然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道调用哪个方法。与C或C++中的函数指针不同,委托使面向对象,而且是类型安全的

foreach迭代器遍历和for循环遍历的区别

foreach:只能通过集合的迭代器直接访问元素,不能直接使用索引。这意味着你无法在循环中修改集合的结构(例如,添加或删除元素),否则将抛出异常。
for:可以通过索引直接访问元素,可以灵活地使用索引进行操作。如果需要在遍历期间对集合进行修改,通常更容易实现。

foreach遍历原理
任何集合类(Array)对象都有一个GetEnumerator()方法,该方法可以返回一个实现了 IEnumerator接口的对象。
这个返回的IEnumerator对象既不是集合类对象,也不是集合的元素类对象,它是一个独立的类对象。
通过这个实现了 IEnumerator接口对象A,可以遍历访问集合类对象中的每一个元素对象
对象A访问MoveNext方法,方法为真,就可以访问Current方法,读取到集合的元素。

C#引用和C++指针的区别

C#不支持指针,但可以使用Unsafe,不安全模式,CLR不检测
C#可以定义指针的类型、整数型、实数型、struct结构体
C#指针操作符、C#指针定义 使用fixed,可以操作类中的值类型
相同点:都是地址
指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

不同点:
指针是个实体,引用是个别名。
sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
引用是类型安全的,而指针在不安全模式下

堆和栈的区别

栈:用于存储局部变量和方法调用信息。当一个方法被调用时,相关的局部变量、参数和返回地址等信息会被压入栈中;当方法执行结束,这些信息会被弹出。
内存的分配和释放非常快速且高效,因为它只需要移动栈指针。栈中的内存是自动管理的,当方法结束时,栈空间会自动释放。
存储在栈上的变量具有块作用域,一旦超出其作用域或方法结束,变量就会被销毁。
主要存放值类型及方法调用的信息

堆:堆是一种用于动态分配内存的数据区域,通常用于存储对象和数据结构。通过 new 关键字创建的对象都会在堆上分配内存,这些对象的生命周期由垃圾回收器(GC)管理。
内存的分配和释放相对较慢,因为它需要查找空闲块并管理复杂的内存碎片。堆中的内存由程序员通过 new 分配,并由垃圾回收器负责最终释放。
存储在堆上的对象的生命周期不受作用域限制,只要有引用指向该对象,它就会继续存在,直到没有引用时才会被垃圾回收器回收。
主要用于存放引用类型以及动态分配的对象

什么是装箱拆箱,怎样减少操作

C#装箱是将值类型转换为引用类型;
拆箱是将引用类型转换为值类型。
牵扯到装箱和拆箱操作比较多的就是在集合中,例如:ArrayList或者HashTable之类。

MVC

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范。

用一种业务逻辑、数据、界面显示分离的方法,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
  通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。
  通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
  通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据

字典Dictionary的内部实现原理

Dictionary 是基于哈希表实现的,哈希表使用哈希函数将键(key)映射到数组中的存储桶(bucket)中。在 Dictionary 中,每个键值对由一个键和相应的值组成。
如果多个键的哈希值冲突(即它们被映射到同一个桶),则这些键值对会以链表的形式存储在该桶内。这种冲突解决方法称为链式散列。
通常用于快速查找和管理映射关系,适合需要快速访问的数据存储场景。

C#中的泛型是什么

在定义泛型类或方法时,可以使用一个或多个类型参数来代替实际的数据类型。
泛型可以减少装箱和拆箱的开销,因为它们允许值类型被直接存储,而无需转换为对象。可以提高性能,减少不必要的类型转换,同时保持代码的灵活性和可维护性。
C# 中的泛型提供了创建可重用、类型安全的代码的能力。
泛型可以用于类、方法和接口,并且支持多种类型约束。

反射的实现原理?

可以在加载程序运行时,动态获取和加载程序集,并且可以获取到程序集的信息反射即在运行期动态获取类、对象、方法、对象数据等的一种重要手段

主要使用的类库:System.Reflection

核心类:

  • Assembly描述了程序集
  • Type描述了类这种类型
  • ConstructorInfo描述了构造函数
  • MethodInfo描述了所有的方法
  • FieldInfo描述了类的字段
  • PropertyInfo描述类的属性

通过以上核心类可在运行时动态获取程序集中的类,并执行类构造产生类对象,动态获取对象的字段或属性值,更可以动态执行类方法和实例方法等。

C#中四种访问修饰符是哪些?各有什么区别?

属性修饰符
存取修饰符
类修饰符
成员修饰符

http://www.lryc.cn/news/447971.html

相关文章:

  • iOS 中的 sqlite-shm 和 sqlite-wal 文件丢失
  • ubuntu22上C/C++程序使用weston+wayland+OpenGLES渲染
  • 打点 - 泛微 E-Cology WorkflowServiceXml
  • Go语言接口与多态
  • 【ADC】SAR 型 ADC 和 ΔΣ ADC 的选型决策方法
  • 探探Java与python中的闭包
  • LD2 Scalable Heterophilous Graph Neural Network with Decoupled Embeddings
  • 【Mysql】Mysql数据库基本操作-------DDL(上)
  • MySQL知识点复习 - 常用的日志类型
  • 基于PHP+MySQL组合开发地方门户分类信息网站源码系统 带完整的安装代码包以及搭建部署教程
  • 【1米C-SAR卫星】
  • 【小小的脑袋,大大的疑问?】如何在Zookeeper中配置集群?
  • Metasploit渗透测试之服务端漏洞利用
  • 什么是原生IP?
  • 【C++】unordered_map(set)
  • HTML 盒模型
  • node.js npm 安装和安装create-next-app -windowsserver12
  • Android13 展锐平台拨号中视频彩铃界面方向未与设备方向一致
  • 为什么IP首部的源IP地址和目的IP地址不变而MAC层的源MAC地址和目的MAC地址变
  • Django 数据库配置以及字段设置详解
  • C++ 左值右值引用梳理
  • 向量化技术在机器学习领域的深度实践与探索
  • RuoYi若依框架学习:多环境配置
  • Linux-RedHat7.4-服务器搭建FTP
  • 遍历递归数结构,修改里的disabled值
  • 怎么通过AI大模型开发一个网站?
  • 【Kubernetes】常见面试题汇总(四十)
  • 数据仓库-数据命名标准规范
  • OCR识别系统 YOLOv8 +Paddle 方案落地
  • 828华为云征文|部署去中心化网络的 AI 照片管理应用 PhotoPrism