面试知识记录——C#

  1. 接口和抽象类的区别:
    抽象类要被子类继承,接口要被子类实现
    接口只能做方法说明,抽象类能做方法说明也能做方法实现
    接口里定义的变量只能是公共的静态的变量,抽象类中的是普通变量
    接口是设计的结果,抽象类是重构的结果
    都是用来抽象具体对象的,但是接口的抽象级别更高
    抽象类可以有具体的方法和属性,接口只能有方法和不可变常量
    抽象类主要是抽象类别,接口主要是抽象功能
  2. 结构体和类的区别:
    结构体是一种值类型,而类是引用类型;
    结构体存储在栈上,类存储在堆上;
    所有结构体成员默认是public,而类的常量和变量默认是private;
    结构体不也能被protected声明,而类可以;
    结构体变量不能声明初始值,而类可以;
    结构体不能声明默认的构造函数,不能声明析构函数,类没有限制;
    结构体无法被继承,类可以被继承;
  3. ref和out的区别:
    效果都是一样的,都是通过关键字找到定义在 主函数里面的变量地址,并且通过方法体内部的语言改变他们的值,不同点是输出参数必须对参数初始化,ref必须初始化,out参数必须在函数里进行赋值,ref参数是引用,out参数是输出参数。
  4. 委托是什么?有什么用处?
    委托类似于一种安全的指针引用,在使用时当作类来看待,而不是一个方法,委托相当于是对一组方法的列表的引用;使用委托时可以将方法引用封装在委托对象内,然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用那个方法,与指针不同的是,委托是面向对象,而且是类型安全的。
  5. 什么是多态?
    同样的操作作用在不同的对象,实现不同的效果。
  6. 什么是泛型?有什么好处?
    泛型就是一种不确定的类型
    好处是省略了强制转换的代码,把运行时的问题提前到了编译时期
  7. 什么是反射?
    是.Net在运行时获取类型信息的方式,可以让程序员在程序运行的期间获得Assembly,Moudle,Class等几个组件的相关信息
  8. 值类型和引用类型
    比较:值类型直接存储数据,引用类型存储数据的地址,数据是存储在堆中的
    主要类别:值类型byte、short、int、long、float、bool、struct、double、decimal、char;    引用类型string、class;
    内存分配:值类型声明之后,不管是否赋值,都会为其分配内存;当声明一个类时,只会在栈中分配一小块内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间,当使用new来创建一个对象实例时,才会分配堆中的内存空间,并把堆上的空间地址保存到栈上分配的内存空间中;所以值类型的实例通常在线程栈上分配的(静态分配),引用类型的实例总是在进程堆上分配的(动态分配)
    使用场合:值类型在内存管理有更好的效率,并且不支持多态,适用于做存储数据的载体,引用类型支持多态,适用于定义应用程序的行为;引用类型可以派生出新的类型,值类型不行,所有的值类型都是密封的sealed;引用类型可以包含null值,值类型不行;引用类型的赋值只复制对象的引用,不复制对象本身,而将一个值类型赋值给另一个值类型变量时,将复制包含的值
  9. 内存分布区域
    栈区:由编译器自动分配释放内存,存放函数的参数值,局部变量的值
    堆区:由程序员分配释放内存,若不释放,程序结束时由系统释放
    全局区:存放全局变量和静态变量,初始化的全局变量和静态变量放在一块区域,未初始化的存放在相邻的一块区域,程序结束时由系统释放
    文本常量区:常量字符串,程序结束时由系统释放
    程序代码区:存放函数的二进制代码
  10. 堆和栈的区别
    堆时动态分配的内存,由程序员在运行时请求
    堆中存放的数据大小和生命周期时不固定的,可以由程序员在运行时控制
    数据在堆中是无序存储的,并且全局可访问
    由于堆中数据需要在运行时动态分配和回收,所以性能上比栈慢
    如果不正确的管理堆内存,可能会导致内存泄漏问题
    栈是自动分配和回收的内存,主要用于存储局部变量和函数调用
    栈中的数据大小和生命周期是固定的,由编译器自动处理
    栈的访问速度比堆块,因为硬件有对栈操作进行优化
    栈中数据的存储按照先进后出的原则存储
    找出栈的大小会导致程序崩溃,也就是常说的栈溢出
  11. 装箱和拆箱
    装箱:将值类型转换为引用类型
    拆箱:将引用类型转换为值类型
    优缺点:
    装箱,提供了一种将原始数据类型转换为对象的方式;装箱允许程序员使用对象提供的各种方法,例如Equals、Hascode;装箱会产生额外的性能开箱,因为需要创建一个新的对象来包装原始值;对象占用的内存通常比原始数据类型多,可能会导致占用更多的内存。
    拆箱,提供了一种将对象转换为原始数据类型的方式,使其可以进行基本的数值运算;一般情况下,原始数据的运行速度快于其包装类;如果尝试拆箱一个null值,会引发空引用异常;
    拆箱可能会导致数据丢失,比如将一个较大的浮点数强制转换为整型;
  12. 装箱和拆箱的过程?
    装箱:将一个值类型装箱为引用类型时,编译器会自动创建一个引用类型的对象,并将值类型的值存储在该对象中。
    拆箱:将一个引用类型对象拆箱为int时,编译器会自动从引用类型对象中提取出值类型的值,使其恢复为原始的值类型数据类型。
  13. GC的流程?
    a.标记(Marking):GC从根对象开始,遍历可达对象图,标记所有被引用的对象。根对象可以时全局变量、活动线程的栈帧中的本地变量等。只有被标记的对象被认为是存活的,未被标记的对象被认为是可回收的。
    b.清楚(Sweeping):在标记完成后,GC会执行清除阶段,遍历堆内存中的所有对象。对于未被标记的对象,GC会将其标记为可回收,并释放它们所占用的内存空间。这些被回收的对象将会被添加到空闲列表中,以备将来的内存分配使用。
    c.压缩(Compacting):在清楚阶段后,可能会进行内存压缩的步骤。内存压缩的目的是将存活的对象紧凑地排列在一起,以便在堆上创建更大的连续空闲内存块。这可以减少内存碎片化,提高内存分配的效率。
    d.内存分配:在清除和压缩之后,GC会将分配请求满足给应用程序,为新对象分配内存空间。
  14. Const和Readonly的区别?
    Const是编译时常量,必须在声明时进行初始化,且不能修改。Readonly是运行时常量,可以在声明时或者构造函数时初始化,且只能在初始化的时候赋值,之后不能修改。
    Const 适用于简单数据类型,如整数和枚举值,而 Readonly 可以用于任何数据类型。
    Const 只能在类的内部和静态成员中使用,而 Readonly 可以在任何成员中使用。
    Const 值在编译时就确定了,所以可以在编译时被嵌入到代码中,不需要在运行时进行计算,因此运行速度较快。而 Readonly 值在运行时才被计算,因此会有一定的运行时开销。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Winjet_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值