龙空技术网

【面试宝典】10个C#.NET 必问基础知识

码上尽宝 790

前言:

如今咱们对“net和接口面试”大致比较关怀,咱们都想要知道一些“net和接口面试”的相关知识。那么小编也在网摘上汇集了一些有关“net和接口面试””的相关文章,希望各位老铁们能喜欢,兄弟们一起来学习一下吧!

本文主要整理10个C#.NET 必问基础知识,这10个知识点不管对于初学程序员还是高级程序员来说都非常重要,如果面试被问到,而你答不上来肯定会被Pass掉。本文整理这些知识点的问题和回答,欢迎大家留言评论,总结更好的问题和回答。谢谢!

1、long的长度,int的长度?float的长度, double的长度?

类型

长度

描述

范围

默认值

bool

1字节

布尔值

True 或 False

False

byte

1字节

8 位无符号整数

0 到 255

0

char

2字节

16 位 Unicode 字符

U +0000 到 U +ffff

'\0'

decimal

16字节

128 位精确的十进制值,28-29 有效位数

(-7.9 x 1028 到 7.9 x 1028) / 100 到 28

0.0M

double

8字节

64 位双精度浮点型

(+/-)5.0 x 10-324 到 (+/-)1.7 x 10308

0.0D

float

4字节

32 位单精度浮点型

-3.4 x 1038 到 + 3.4 x 1038

0.0F

int

4字节

32 位有符号整数类型

-2,147,483,648 到 2,147,483,647

0

long

8字节

64 位有符号整数类型

-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807

0L

sbyte

1字节

8 位有符号整数类型

-128 到 127

0

short

2字节

16 位有符号整数类型

-32,768 到 32,767

0

uint

4字节

32 位无符号整数类型

0 到 4,294,967,295

0

ulong

8字节

64 位无符号整数类型

0 到 18,446,744,073,709,551,615

0

ushort

2字节

16 位无符号整数类型

0 到 65,535

0

2、 C# 值类型与引用类型?

在 .NET 中,数据类型可以分为值类型和引用类型。

值类型:

值类型的变量直接存储其值,而不是引用到内存中的对象。值类型包括基本数据类型(如整数、浮点数、布尔值等)以及结构体(struct)。值类型的变量在栈上分配内存,它们的生命周期与其所在的作用域相对应。

引用类型

引用类型的变量存储的是对对象的引用,而不是对象本身。引用类型包括类(class)、接口(interface)、委托(delegate)和数组等。引用类型的变量在栈上分配内存,但实际的对象存储在堆上,它们的生命周期由垃圾回收器来管理。

值类型和引用类型的区别:

值类型的变量直接存储值,而引用类型的变量存储对对象的引用。值类型的变量访问速度较快,因为它们直接存储在栈上。而引用类型的变量访问速度较慢,因为需要先通过引用找到对象所在的堆。值类型的变量在传递给方法时,会进行值的拷贝。而引用类型的变量在传递给方法时,传递的是引用的副本,即指向同一个对象的引用。3、C#装箱和拆箱是什么?有那些缺点,平时该如何避免?

在C#中,装箱(Boxing)和拆箱(Unboxing)是将值类型(如int、bool等)转换为引用类型(如object)和将引用类型转换为值类型的过程。

装箱是将值类型的值包装到一个对象中,以便能够将其存储在引用类型的变量中或传递给需要引用类型参数的方法。拆箱则是从装箱的对象中提取出值类型的值。

装箱和拆箱的缺点主要有以下几点:

性能开销:装箱和拆箱操作会导致额外的性能开销,因为它们涉及到内存分配和数据复制。内存占用:装箱会创建一个新的对象来存储值类型的值,这会占用额外的内存空间。引发异常:如果拆箱操作尝试将一个不正确类型的对象转换为值类型,会引发InvalidCastException异常。

为了避免装箱和拆箱的缺点,可以采取以下措施:

尽量使用值类型:在设计和选择数据结构时,尽量使用值类型而不是引用类型,以避免装箱和拆箱的开销。使用泛型集合:使用泛型集合(如List、Dictionary等)来存储和操作数据,避免使用非泛型集合(如ArrayList、Hashtable等)。使用强类型转换:在需要将引用类型转换为值类型时,使用强类型转换(如int.Parse、Convert.ToInt32等)而不是拆箱操作。避免频繁的装箱和拆箱:尽量避免在循环或高频率的操作中进行频繁的装箱和拆箱操作,可以通过缓存对象或使用缓存变量来减少装箱和拆箱的次数。4、C#接口与抽象类有什么区别?

C# 中的接口(interface)和抽象类(abstract class)都是用于实现多态性和代码重用的机制,但它们在一些方面有着不同的特点和用途。

定义方式:接口是一种纯粹的契约,只定义了一组成员的签名,不包含实现代码。抽象类则可以包含具体的实现代码,同时也可以定义抽象成员。继承关系:类可以同时实现多个接口,但只能继承一个抽象类。接口之间没有继承关系,而抽象类可以通过继承来建立层次关系。实现方式:类实现接口时需要显式地声明并实现接口中的所有成员。对于抽象类,子类需要使用关键字 "override" 来重写抽象成员,并可以选择性地重写非抽象成员。使用场景:接口适用于定义一组相关的功能,用于实现多态性和实现类之间的松耦合,可以用于实现多个不相关的类。抽象类适用于定义一组相关的功能,并且可以提供一些默认的实现,用于实现类之间的继承关系。实例化:接口不能被实例化,只能被实现。抽象类可以被继承并实例化。5、值类型与引用类型在GC 和内存分别有什么不同?

值类型和引用类型在GC和内存方面有以下不同之处:

内存分配:值类型的变量通常存储在栈上,而引用类型的对象存储在堆上。栈上的内存分配和释放速度快,但大小有限;堆上的内存分配和释放速度相对较慢,但大小通常比栈大得多。

内存管理:值类型的变量在超出其作用域时会自动释放,无需手动管理内存。而引用类型的对象在不再被引用时,由垃圾回收机制自动回收其占用的内存。

垃圾回收:值类型的变量不会被垃圾回收器跟踪和回收,因为它们的生命周期是由其作用域控制的。而引用类型的对象会被垃圾回收器跟踪,并在不再被引用时自动回收其占用的内存。

传递方式:值类型的变量在方法调用时,会将其实际值复制到新的变量中,方法内部对新变量的修改不会影响原变量的值。而引用类型的对象在方法调用时,会将其引用复制到新的变量中,方法内部对新变量的修改会影响原对象的值。

6、谈谈委托和事件你怎么理解的?

委托是一种类型,用于引用方法,并允许将方法作为参数传递给其他方法。它类似于函数指针,在C#中可以用来实现回调函数的功能。委托定义了方法的签名(返回类型和参数类型),可以通过委托的实例来引用具有相同签名的方法。委托可以用来解耦调用者和被调用者,使得代码更加灵活和可扩展。

事件是委托的一种特殊用法,用于实现观察者模式。事件是类或对象的成员,它定义了一种特殊的委托类型,只能通过事件的添加和移除操作来注册和注销事件处理方法。事件可以在特定条件下触发,当事件触发时,所有注册的事件处理方法会被依次调用。事件的使用可以实现对象之间的松耦合,使得代码更加可维护和可测试。

7、谈谈.NET中的GC机制?

在 .NET Core 中,垃圾回收器(Garbage Collector,GC)是一种自动内存管理机制,用于管理和释放不再使用的对象。垃圾回收器的主要机制如下:

分代垃圾回收:.NET Core 的垃圾回收器使用了分代垃圾回收的概念。它将堆内存分为三代:0代、1代和2代。新创建的对象被分配在0代,当0代满时会触发垃圾回收,回收不再使用的对象。如果某个对象经过多次垃圾回收后仍然存活,它会被提升到更高的代。标记-清除算法:垃圾回收器使用标记-清除算法来确定哪些对象是可达的(即仍然被引用),哪些对象是不可达的(即不再被引用)。垃圾回收器首先从根对象(如全局变量、静态变量等)开始,递归地遍历对象图,并标记所有可达的对象。然后,它会清除所有不可达的对象,并释放它们所占用的内存。垃圾回收器线程:垃圾回收器运行在一个或多个专用的线程上。默认情况下,垃圾回收器线程与应用程序线程并行运行,以减少对应用程序的影响。垃圾回收器线程会在特定条件下触发垃圾回收,并在回收过程中暂停应用程序线程。托管堆(Managed Heap):在 .NET Core 中,对象被分配在托管堆上。托管堆是一块内存区域,用于存储和管理对象。垃圾回收器负责在托管堆上分配和释放内存。最终器(Finalizer):在对象被回收之前,垃圾回收器会调用对象的最终器(Finalizer),用于执行对象的清理操作。最终器是在对象被回收之前的一个阶段执行的,但它不保证一定会执行。内存压缩(Memory Compaction):为了减少内存碎片化,垃圾回收器会对堆内存进行压缩。内存压缩会将存活的对象移动到堆的一端,以便在堆的另一端创建更大的连续空间。8、C#语言中的Thread 的sleep() 和 Task.Delay() 有什么区别?

在C#语言中,Thread.Sleep()和Task.Delay()都可以用于在代码中添加延迟,Thread.Sleep()是同步的,会阻塞当前线程;Task.Delay()是异步的,不会阻塞当前线程。Thread.Sleep()会暂停线程的执行,而Task.Delay()通过计时器来实现延迟,可以在等待期间继续执行其他任务。另外,Task.Delay()还可以与异步编程模型(如async/await)结合使用,提供更好的异步编程体验。

9、C# 中Equals 和 == 的区别?

1、Equals是一个实例方法,而==是一个运算符。

2、Equals方法是用于比较两个对象的值是否相等,它是Object类的虚方法,可以被子类重写。默认情况下,Equals方法比较的是对象的引用是否相等,即比较对象的内存地址。可以通过重写Equals方法来自定义对象的相等比较逻辑。

3、==运算符用于比较两个对象是否相等。对于引用类型,==比较的是对象的引用是否相等,即比较对象的内存地址。对于值类型,==比较的是对象的值是否相等。可以通过重载==运算符来自定义对象的相等比较逻辑。

4、对于值类型,Equals方法和==运算符的行为是相同的,都是比较对象的值是否相等。

5、对于引用类型,Equals方法和==运算符的行为可能不同。默认情况下,Equals方法比较的是对象的引用是否相等,而==运算符比较的是对象的引用是否相等。但是,可以通过重写Equals方法来改变引用类型对象的相等比较逻辑。

10、C#多线程和异步的区别和联系?

区别:

执行方式:多线程是通过创建和管理多个线程来实现并发执行,每个线程独立执行任务。异步是通过使用异步操作和回调机制来实现并发执行,任务可以在单个线程上执行,避免了线程切换的开销。

编程模型:多线程需要显式地创建、启动和管理线程,需要注意线程同步和互斥。异步使用异步操作和回调机制,可以使用async/await关键字来简化异步编程,不需要手动管理线程。

资源消耗:多线程需要创建和管理多个线程,会消耗更多的系统资源。异步使用单个线程执行任务,减少了线程切换的开销,节省了系统资源。

联系:

并发执行:多线程和异步都可以实现任务的并发执行,提高程序的响应性和吞吐量。

异步编程:多线程和异步都可以用于实现异步编程,处理耗时的操作,避免阻塞主线程。

线程同步:多线程和异步都需要考虑线程同步和互斥,以避免竞态条件和数据不一致的问题

标签: #net和接口面试