C# 于 2000 年首次亮相,已成功成为领先的编程语言之一。作为一种多范式编程语言,C# 还具有函数式编程的一些特性,使其实用性和通用性更上一层楼。
C#常见面试问题和答案合集
在下一节中,我们列出了最重要的 C# 面试问题。这些问题不仅可以增强你的 C# 知识并让你评估你当前对 C# 的理解,还可以为你的下一次 C# 面试做好准备。
问题:什么是 C#?写出它的特点
答: C#是微软在2000年开发的面向对象的编程语言,支持不同的操作系统。C# 是用于创建 .Net 软件应用程序的主要语言。它允许我们创建 Windows UI 应用程序、后端服务、控件、库、Android 应用程序,甚至区块链应用程序。C# 像 Java 一样处理类和对象的概念。
一些 C# 特性如下:
- 遵循结构化方法
- 参数传递很容易
- 代码可以在不同的平台上编译
- 开源
- 面向对象
- 灵活和可扩展
C#常见面试题有哪些:解释一下 C# 中的类和对象是什么?
答: C# 是一种面向对象的语言,类是它的基础。类通常描述数据的结构,以及如何在程序中存储和管理数据。一个类有它自己的属性、方法和其他定义该类的对象。
对象是具有某些特征的现实世界实体,是使用类实例创建的。这些类定义了已定义对象的类型。
例如,如果我们考虑一个涵盖与书相关的对象的程序。我们称这个类为 Book ,它有两个属性:名字和作者。在实际编程中,Vedas 是类 Book 的一个对象和实例。
问题:详细描述不同的 C# 类。
C#面试题解析: 我们可以在 C# 中使用 4 种类型的类:
- 静态类:它是不能被实例化的类的类型,换句话说,我们不能使用 new 关键字创建该类的对象,并且可以使用它们的类名直接调用类成员。
- 抽象类:抽象类是使用抽象关键字声明的。不能为抽象类创建对象。如果要使用它,则必须在子类中继承它。你可以轻松地在 Abstract 类中定义抽象或非抽象方法。抽象类中的方法可以有实现也可以没有实现。
- Partial Class:它是一种类,允许将它们的属性、方法和事件分成多个源文件,并在编译时将这些文件组合成一个类。
- 密封类: 不能从另一个类继承密封类并限制类属性。任何访问修饰符都不能应用于密封类。
问题:解释 C# 中的不同访问修饰符?
答:这些关键字有助于定义程序中类、成员和数据类型的可访问性。这些关键字用于限制使用其他类完成的某些数据操作。有 4 种类型的访问修饰符 - public、private、protected 和 internal。这些修饰符在协同工作时定义了 6 个其他可访问性级别 - public、protected、internal、protected internal、private 和 private protected。
下面是修改器的访问图表。
PUBLIC | PROTECTED | INTERNAL | PROTECTED INTERNAL | PRIVATE | PRIVATE PROTECTED | |
完整程序 | Yes | No | No | No | No | No |
当前程序集中的派生类型 | Yes | Yes | No | Yes | No | Yes |
使用类 | Yes | Yes | Yes | Yes | Yes | Yes |
当前装配 | Yes | No | Yes | Yes | No | No |
派生数据类型 | Yes | Yes | No | Yes | No | No |
问题:你如何详细描述面向对象的概念?
答: C# 是一种面向对象的编程语言,支持 4 个OOP 概念。
- 封装:定义将代码和数据绑定在一起,并使其免受其他程序和类所做的任何操作的影响。它是一个容器,可防止代码和数据被在容器外部定义的另一个程序访问。
- 抽象:这个面向对象的概念保护除了有关任何创建的对象的相关数据之外的所有内容,以提高程序内的效率和安全性。
- 继承:继承的应用方式是一个对象使用另一个对象的属性。
- 多态性:是一种特性,它允许一个接口充当其他类的基类。这个概念通常被表达为“单一界面但多个动作”。
C#常见面试问题和答案合集:解释如何在 C# 中编译代码?
答:需要 4 个步骤才能获得在 C# 中编译的代码。以下是步骤:
- 首先,在与C#编译器兼容的托管代码中编译源代码。
- 其次,将上面新创建的代码组合成程序集。
- 第三,加载CLR。
- 最后,通过 CLR 执行程序集以生成输出。
问题:什么是 C# 中的 break 和 continue 语句,解释一下?
答: 区别如下:
break | continue |
你可以在 switch 和循环(for、while 和 do-while)语句中使用 break 语句。 | 你只能在循环(for、while、do)语句中使用 continue 语句。 |
switch 或 loop 语句在执行 break 语句时终止,并从那里突然结束。 | 你不能让 continue 语句终止循环,它会继续循环以进入下一个迭代级别,而不会立即执行下一步。 |
当编译器遇到break语句并退出内循环时,循环或开关立即退出内循环。 | 放置在 switch 内嵌套循环内的 continue 会导致下一次循环迭代。 |
问题:如何详细解释 C# 中“using”语句的使用。
答: using 语句用于控制程序中正在使用的一个或多个资源的使用。资源不断消耗和释放。该语句的主要功能是管理未使用的资源并自动释放它们。一旦创建了使用资源的对象,完成后确保调用对象的 dispose 方法以释放该对象使用的资源,这就是 using 语句工作良好的地方。
例如:
using (MyResource abc = new MyResource())
{
abc.program();
}
Gets translated to,
MyResource abc= new MyResource();
try
{
myRes.program();
}
finally
{
// Check for a null resource.
if (abc!= null)
// Call the object's Dispose method.
((IDisposable)abc).Dispose();
}
问题:详细描述C#的dispose方法。
答:Dispose方法: disposeof()方法通过类的对象释放未使用的资源。未使用的资源,如文件、数据连接等。该方法在名为IDisposable的接口中声明,该接口由类通过定义接口 IDisposable 主体实现。Dispose 方法不是自动调用的,程序员必须手动实现它以有效利用资源。
问题:详细解释一下C#中的finalize方法?
答案:Finalize 方法- finalize() 方法在用于清理活动的对象类中定义。每当任何对象的引用长时间不使用时,垃圾收集器通常都会调用此方法。垃圾收集器会自动释放管理的资源,但如果你想释放未使用的资源,如文件句柄、数据连接等,则必须手动实现 finalize 方法。
C#常见面试题有哪些:如何在 C# 中定义异常处理?
答:异常是程序执行过程中可能出现的引发的问题。处理异常提供了一种在引发异常时在程序内传递控制的简单方法。C# 异常是通过使用 4 个关键字来处理的,它们是 try、catch、finally、throw。
- try:引发的异常找到要处理的特定代码块。你将在程序中用于处理引发的不同类型异常的 catch 块的数量没有限制。
- catch: 你可以在此 catch 块中处理引发的异常。你可以提及要解决错误的步骤,也可以通过代码抑制错误来忽略错误。
- finally: 不管错误如何,如果你仍然希望显示一些指令集,那么你可以在 finally 块中使用这些语句,它会在屏幕上显示它。
- throw: 你可以使用 throw 语句抛出异常。它将显示你遇到的错误类型。
句法:
try {
//exception handling starts with try block
} catch( ExceptionName ea1 ) {
// errors are handled within the catch block
} catch( ExceptionName e2 ) {
// more catch block
} catch( ExceptionName eN ) {
// more catch block to handle multiple exception raised
} finally {
// last block of the exception handling
}
问题:详细解释析构函数的概念。用一个例子来解释它。
C#面试题解析: 析构函数是与构造函数相反的成员。与构造函数不同,析构函数主要是删除对象。析构函数名称必须与类名称完全匹配,就像构造函数一样。析构函数块始终以波浪号 (~) 符号开头。
句法:
~class_name()
{
//code
}
自动调用析构函数:
- 当程序完成执行时。
- 每当程序的范围结束时,就会定义一个局部变量。
- 每当你从程序中调用删除运算符时。
问题:用例子定义方法重载。
答:方法重载允许程序员使用多个名称相同的方法。程序中每个定义的方法都可以根据方法参数的数量和类型进行区分。它是一个基于多态的概念。
方法重载可以通过以下方式实现:
- 通过改变给定方法中的参数数量
- 通过改变传递给方法的参数顺序
- 通过使用不同的数据类型作为传递的参数
例如:
public class Methodoveloading
{
public int sum(int a, int b) //two int type Parameters method
{
return a + b;
}
public int sum(int a, int b,int c) //three int type Parameters with same method same as above
{
return a + b+c;
}
public float sum(float a, float b,float c,float d) //four float type Parameters with same method same as above two method
{
return a + b+c+d;
}
}
C#常见面试问题和答案合集:C#中使用的控制语句有哪些?
答:你可以使用控制语句来控制指令集的流程,我们主要关注 if 语句。我们考虑使用几种类型的 if 语句来创建控制程序内执行流程的情况。
这些是 4 种类型的 if 语句:
- If
- If-else
- 嵌套if
- If-else-if
这些语句通常在程序中使用。
If 语句检查用户给定的条件以满足他们的编程条件。如果它返回真,那么这组指令将被执行。
句法:
If(any condition)
{
//code to be executed if the condition returns true
}
If-else 语句检查给定的条件,如果条件为假,则流程将转移到 else 语句,并执行 else 指令。如果 if 条件为真,则将执行 if 指令。
句法:
If(condition)
{
//code to be run if the condition is true
}
Else
{
//code to be run if the if-condition is false
}
嵌套 if 语句检查条件,如果条件为真,则它将检查内部 if 语句并继续检查最后一个 if 语句。如果任何条件为真,那么它将执行特定的 if 指令并在那里停止 if 循环。
句法:
If (condition to be checked)
{
//code
If(condition 2)
{
//code for if-statement 2
}
}
如果 else-if 检查给定的条件,如果条件不为真,则控件将转到下一个 else 条件,如果该条件不为真,它将继续检查下一个 else 条件。如果任何条件未通过,则将执行最后的 else 指令。
句法:
If(condition 1 to be checked)
{
//code for condition 1
}
Else (condition 2 to be checked)
{
//code for condition 2
}
Else
{
//code will run if no other condition is true
}
问题:解释C#中值类型和对象类型的装箱和拆箱的概念。
回答:
装箱- 是将值类型转换为对象类型的过程,其中值类型放置在堆栈内存中,对象类型放置在堆内存中。此转换是隐式转换,你可以直接为对象分配任何值,C# 将自行处理其余的转换。
例子:
public void function()
{
Int a=111;
Object b=a; //implicit conversion
Console.WriteLine(b);
}
拆箱- 这是装箱过程的逆过程。它是对象类型到值类型的转换,放在堆内存上的装箱对象类型的值将被转移到放在堆栈上的值类型。必须明确完成拆箱过程的这种转换。
例子:
public void function()
{
Object b=111;
Int a=(int)b; //implicit conversion
Console.WriteLine(a);
}
问题:如何使用 C# 检查一个数字是否为 Armstrong 数字?
回答:
using System;
public class ArmstrongDemo
{
public static void Main(string[] args)
{
int n,b,sum=0,num;
Console.Write("Enter the Number= ");
n= int.Parse(Console.ReadLine());
num=n;
while(n>0)
{
b=n%10;
sum=sum+(b*b*b);
n=n/10;
}
if(num==sum)
Console.Write("Armstrong Number.");
else
Console.Write("Not Armstrong Number.");
}
}
输出:
Enter the Number= 371
Armstrong Number.
问题:在 C# 中传递参数的不同方法是什么?
答: 参数可以通过三种不同的方式传递给任何定义的方法,它们的定义如下:
值参数: 它将参数的实际值传递给形参。在这种情况下,对函数形式参数所做的任何更改都不会影响参数的实际值。
引用参数:使用此方法,你可以将引用内存位置的参数复制到形式参数中,这意味着对参数所做的任何更改都会影响该参数。
输出参数:此方法向该方法返回多个值。
问题:什么是 C# 中的多播委托?
回答:多播委托一次保存对多个函数的引用或地址。每当我们调用多播委托时,它都会调用该多播委托引用的所有其他函数。你应该使用与委托相同的完整方法签名来调用多个方法。例如:
namespace MulticastDelegate
{
public class Rectangle
{
public void Area(double Width, double Height)
{
Console.WriteLine(@"Area is {0}", (Width * Height));
}
public void Perimeter(double Width, double Height)
{
Console.WriteLine(@"Perimeter is {0}", (2 * (Width + Height)));
}
static void Main(string[] args)
{
Rectangle rect = new Rectangle();
rect.Area(23.45, 67.89);
rect.Perimeter(23.45, 67.89);
Console.ReadKey();
}
}
}
在这里,我们创建了一个Rectangle类的实例,然后调用了两个不同的方法。现在单个委托将调用这两个方法Area和Perimeter。这些已定义的方法与持有对这些方法的引用的已定义委托具有相同的签名。
创建多播委托:
namespace MulticastDelegateDemo
{
public delegate void RectangleDelete(double Width, double Height);
public class Rectangle
{
public void Area(double Width, double Height)
{
Console.WriteLine(@"Area is {0}", (Width * Height));
}
public void Perimeter(double Width, double Height)
{
Console.WriteLine(@"Perimeter is {0}", (2 * (Width + Height)));
}
static void Main(string[] args)
{
Rectangle rect = new Rectangle();
RectangleDelete rectDelegate = new RectangleDelete(rect.Area);
rectDelegate += rect.Perimeter;
rectDelegate(23.45, 67.89);
Console.WriteLine();
rectDelegate.Invoke(13.45, 76.89);
Console.WriteLine();
//Removing a method from delegate object
rectDelegate -= rect.Perimeter;
rectDelegate.Invoke(13.45, 76.89);
Console.ReadKey();
}
}
}
问题:如何在 C# 中实现 nullable<> 类型?用 Nullable 类型的语法解释一下。
C#面试题解析:在 C# 中,不能将空值直接放入任何变量中,编译器也不支持。因此,修订版C# 2.0为你提供了一个特殊功能,该功能将为称为 Nullable 类型的变量分配空值。你不能使可为 null 的类型与值类型一起使用。可空值只能与引用类型一起使用,因为它已经有一个空值。System.Nullable<T> 结构创建实例可为空类型,其中 T 定义数据类型。这个 T 包含一个不可为空的值类型,它可以是你想要的任何数据类型。
句法
Nullable<data_type> variable_name= null ;
或者
Datatype? variable_name=null;
你不可能通过分配值直接访问可为空值类型的值。要获取其原始分配值,你必须使用方法 GetValueOrDefault()。如果该值为空,则它将提供零,因为它是其默认值。
问题:C# 中的值类型和引用类型是什么意思?
回答:
值类型:
为值类型内容或分配的值分配的内存存储在堆栈中。当我们创建任何变量时,都会为该变量分配空间,然后可以为该变量分配一个值。此外,如果我们想将该变量的值复制到另一个变量,它的值将被复制并创建两个不同的变量。
参考类型:
它保存对对象地址的引用,但不直接保存对象。引用类型表示变量的地址,将引用变量分配给另一个引用变量不会复制数据,但会创建引用的第二个副本,该副本表示与原始值在堆上相同的位置。引用值存储在堆上,当不再需要引用变量时,它会被标记为垃圾收集。
问题:C#中有哪些不同类型的注释,请举例说明?
答: C#支持三种类型的注释——
1.单行注释
语法: //单行
2. 多行注释
语法: /* 多行
*/
3. XML 注释
语法: /// 设置错误
问题:构造函数是什么?
答:在 C# 中,有一个特殊的方法,它会在对象创建时自动调用。它初始化新对象的数据成员,并与类或结构具有相同的名称。有两种类型的构造函数:
- 默认构造函数:它没有要传递的参数。
- 参数化构造函数:使用对象创建期间传递给类的参数调用它。
问题:C# 中有哪些不同的集合类?
答:集合类是主要用于数据存储和检索的类。这些集合类将用于许多目的,例如在运行时分配动态内存,你甚至可以使用索引值访问集合的项目,这使搜索更容易、更快。这些集合类属于对象类。
有很多集合类,如下所示:
数组列表: 它指的是单独索引的对象的有序集合。你可以将其用作数组的替代品。使用索引,你可以轻松地从列表中添加或删除项目,它会自动调整大小。它适用于动态内存分配、添加或搜索列表中的项目。
哈希表:如果要访问哈希表的项,则可以使用键值来引用变量的原始分配值。哈希表中的每个项目都存储为一个键/值对,并且该项目以其键值进行引用。
栈: 它适用于对象的后进先出集合的概念。每当你将项目添加到列表时,它称为推送,当你从列表中删除项目时,它称为弹出。
排序列表: 这个集合类使用键和索引的组合来访问列表中的项目。
队列:这个集合基于对象的先进先出集合的概念。将项目添加到列表是调用入队,从列表中删除项目是调用双端队列。
BitArray: 该集合类用于以二进制形式(0 和 1)表示数组。当你不知道数字并且可以使用从零开始的整数索引访问项目时,你可以使用此集合类。
C#常见面试问题和答案合集:解释 C# 中的文件处理。
回答:每当你打开文件进行读取或写入时,它都会变成一个流,它是从源到目的地的字节序列。两个常用的流是输入和输出。包含的命名空间是 system.IO,其中包含许多用于文件处理的类。流是一个抽象类,它是文件处理过程的父类。文件是一个静态类,有很多静态方法来处理文件操作。
以下是使用的类:
下表描述了 System.IO 命名空间中的一些常用类。
类名称 | 描述 |
FileStream | 此流从文件中的任何位置读取和写入 |
BinaryReader | 从二进制流中读取原始数据类型 |
DirectoryInfo | 对目录执行操作 |
FileInfo | 对文件执行操作 |
BinaryWriter | 以二进制格式写入原始数据类型 |
StreamReader | 从字节流中读取字符 |
StreamWriter | 将字符写入流。 |
StringReader | 从字符串缓冲区读取 |
StringWriter | 写入字符串缓冲区 |
C#常见面试题有哪些:在C#中定义接口类?举例说明。
答:接口类完全是一个包含抽象方法和属性的抽象类。默认情况下,接口类的成员是抽象和公共的,没有定义任何字段。如果要访问接口方法,则该接口必须由另一个类使用“:”符号实现。如果要定义只能在实现类中实现的方法的主体。
例如:
// Interface
Interface IAnimal {
void Sound(); // interface method (without body)
}
class Pig : IAnimal // Pig class "implements" the IAnimal interface
{
public void Sound()
{
Console.WriteLine("The pig says: wee wee"); // The body of Sound() is provided her
}
}
class Program
{
static void Main(string[] args)
{
Pig myPig = new Pig(); // Create a Pig object
myPig.animalSound();
}}
问题:解释C#中线程的概念。
答:线程可以定义为任何程序的执行流程,并定义一个独特的控制流程。你可以管理这些线程的执行时间,以便它们的执行不会与其他线程的执行重叠并防止死锁或保持资源的有效使用。线程是轻量级的程序,可以节省 CPU 消耗并提高应用程序的效率。线程循环从 system.threading.thread 类对象的创建开始,并在线程终止时结束。
System.threading.thread 类允许你处理多个线程,并且第一个线程始终运行在称为主线程的进程中。每当你在 C# 中运行程序时,主线程都会自动运行。
问题:用示例在 C# 中定义结构。
答:结构是值类型的数据类型。当你要定义结构时,会使用 struct 关键字。一个结构代表一个记录,这个记录可以有许多定义结构的属性。你可以为结构定义构造函数,但不能定义析构函数。你可以在结构中实现一个或多个接口。你可以指定一个结构,但不能指定为抽象的、虚拟的或受保护的。如果不使用 new 运算符,结构的字段将保持未分配状态,并且在初始化字段之前不能使用该对象。
问:C#中的用户控件和自定义控件是什么意思?
答:用户控件非常容易创建,并且与 ASP 控件文件非常相似。你不能在工具箱上放置用户控件,甚至不能拖放它。它们在这些控件背后具有独特的设计和单独的代码。Ascx 是用户控制的文件扩展名。
你可以创建自定义代码作为编译后的代码并可以添加到工具箱中。你可以轻松地将这些控件包含到 Web 表单中。自定义控件可以有效地添加到多个应用程序中。如果要添加私有自定义控件,则可以将其复制到 dll,然后复制到 Web 应用程序的 bin 目录,并在那里使用其引用。
问题:C# 程序从队列中删除一个元素。
回答:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Application
{
class DemoProgram
{
static void Main(string[] args)
{
Queue qs = new Queue();
qs.Enqueue(1);
qs.Enqueue(2);
qs.Enqueue(3);
foreach (Object ob in qs)
{
Console.WriteLine(ob);
}
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Total number of elements in the Queue " + qs.Count);
Console.WriteLine("Does the Queue contain " + qs.Contains(3));
Console.ReadKey();
}
}
}
问题:如何在 C# 中查找数字是否为回文数。
回答:
using System;
public class PalindromeNum
{
public static void Main(string[] args)
{
int n,r,num=0,Dem;
Console.Write("Enter the Number: ");
n = int.Parse(Console.ReadLine());
dem=n;
while(n>0)
{
r=n%10;
num=(num*10)+r;
n=n/10;
}
if(dem==num)
Console.Write("Number is Palindrome.");
else
Console.Write("Number is not Palindrome");
}
}
问题:你将如何区分类和结构?
答:虽然类和结构都是用户定义的数据类型,但它们在几个基本方面是不同的。类是一种引用类型并存储在堆中。另一方面,结构是一种值类型,因此存储在堆栈中。虽然该结构不支持继承和多态,但该类为两者提供了支持。类可以是抽象类型,但结构不能。默认情况下,类的所有成员都是私有的,而结构的成员默认是公共的。class 和 struct 之间的另一个区别是基于内存管理。前者支持垃圾回收,后者不支持。
问题:比较虚拟方法和抽象方法。
答:任何虚拟方法都必须有一个默认实现,并且可以在派生类中使用 override 关键字覆盖它。相反,抽象方法没有实现,它驻留在抽象类中。派生类必须实现抽象方法。虽然不是必需的,但我们可以在这里使用 override 关键字。
问题:什么是 C# 中的命名空间?
答:命名空间的使用是为了组织大型代码项目。C# 中使用最广泛的命名空间是 System。命名空间是使用命名空间关键字创建的。可以在另一个命名空间中使用一个命名空间,称为嵌套命名空间。
问题:什么是 C# 中的 I/O 类?定义一些最常用的。
答:C# 中的 System.IO 命名空间由几个类组成,用于执行各种文件操作,例如创建、删除、关闭和打开。C# 中一些最常用的 I/O 类是:
- File - 操作文件
- Path - 执行与某些路径信息相关的操作
- StreamReader – 从流中读取字符
- StreamWriter – 将字符写入流
- StringReader – 读取字符串缓冲区
- StringWriter – 写入字符串缓冲区
问题:你对C#中的正则表达式的理解是什么?编写一个使用正则表达式搜索字符串的程序。
答:正则表达式是匹配一组输入的模板。它可以由结构、字符文字和运算符组成。正则表达式用于字符串解析,以及替换字符串。以下代码使用正则表达式针对来自语言数组的输入集搜索字符串“C#”:
static void Main(strong[] args)
{
string[] languages = {“C#”, “Python”, “Java”};
foreach(string s in languages)
{
if(System.Text.RegularExpressions.Regex.IsMatch(s,“C#”))
{
Console.WriteLine(“Match found”);
}
}
}
问题:详细解释C#中的Delegates。
答:委托是保存对方法的引用的变量。它是一个函数指针或引用类型。Delegate 和它所引用的方法都可以具有相同的签名。所有代表均来自
System.Delegate namespace.
以下示例演示了声明委托:
public delegate AddNumbers(int n);
声明委托后,必须使用 new 关键字为委托创建对象,例如:
AddNumbers an1 = new AddNumbers(number);
Delegate 提供了一种对引用方法的封装,它通过委托的调用在内部被调用。在下面的例子中,我们有一个委托 myDel,它接受一个整数值作为参数: public delegate int myDel(int number); public class Program { public int AddNumbers(int a) { Int Sum = a + 10; 返回总和;} public void Start() { myDel DelgateExample = AddNumbers; } }
问题:解释 C# 中的反射。
答:代码在运行时访问程序集元数据的能力称为反射。程序反思自身并使用元数据来:
- 通知用户,或
- 修改行为
该系统包含管理所有加载的类型和方法的信息的所有类和方法。反射命名空间。反射的实现分两步:
- 获取对象的类型,然后
- 使用类型来标识成员,例如属性和方法
问题:列举一些在 C# 中查找死锁的最常见位置。
回答:为了识别死锁,应该寻找卡在以下其中一项上的线程:
- .Result、.GetAwaiter().GetResult()、WaitAll() 和 WaitAny()(使用任务时)
- Dispatcher.Invoke()(在 WPF 中工作时)
- Join()(使用线程时)
- 锁定语句(在所有情况下)
- WaitOne() 方法(使用 AutoResetEvent/EventWaitHandle/Mutex/Semaphore 时)
问题:在 C# 中定义序列化及其各种类型。
答:将某些代码转换为其二进制格式的过程在 C# 中称为序列化。这样做可以让代码轻松存储并写入磁盘或其他存储设备。当严格需要不丢失代码的原始形式时,我们使用序列化。标有 [Serializable] 属性的类被转换为其二进制形式。包含序列化对象和 System.Runtime.Serialization 命名空间的流可以具有用于序列化的类。C#中的序列化分为三种类型:
- 二进制序列化 -更快,需要更少的空间;它将任何代码转换为其二进制形式。序列化和恢复公共和非公共属性。
- SOAP –它生成一个完整的 SOAP 兼容信封,可供任何能够理解 SOAP 的系统使用。有关此类序列化的类驻留在 System.Runtime.Serialization 中。
- XML 序列化 – 将所有公共属性序列化为 XML 文档。除了易于阅读之外,XML 文档还以多种格式进行操作。此类序列化中的类驻留在 System.sml.Serialization 中。
注意:从二进制形式检索 C# 代码称为反序列化。
问题:简要说明 C# 中的线程池。
答:线程的集合,在 C# 中称为线程池。此类线程用于在不干扰主线程执行的情况下执行任务。属于线程池的线程执行完毕后,返回线程池。管理线程池中的线程及其操作的类包含在 System.Threading.ThreadPool 命名空间中。
问题:是否可以在 C# 的静态方法中使用 this 关键字?
C#面试题解析:一种特殊类型的引用变量,这个关键字被隐含地定义在每个非静态方法和构造函数中,作为定义它的类型类的第一个参数。静态方法不属于特定实例。相反,它们存在而不创建类的实例并使用类的名称进行调用。由于此关键字返回对包含它的类的当前实例的引用,因此不能在静态方法中使用。虽然我们不能在静态方法中使用这个关键字,但我们可以在扩展方法的函数参数中使用它。
问题:关于 C# 中的 XSD 文件,你能告诉我们什么吗?
答:XSD 表示 XML 架构定义。如果没有与之关联的 XSD 文件,则 XML 文件可以具有任何属性、元素和标记。XSD 文件为 XML 文件提供了一个结构,这意味着它决定了 XML 文件中应该包含哪些元素和属性以及元素和属性的顺序。注意: - 在 C# 代码的序列化过程中,Xsd.exe 工具将类转换为 XSD 兼容格式。
问题:C# 中的构造函数链是什么意思?
答:C# 中的构造函数链是一种将关系中的两个或多个类作为继承连接起来的方法。每个子类构造函数都通过在构造函数链中使用 base 关键字隐式映射到父类构造函数。
问题:在 C# 中解释线程的不同状态?
答:C# 中的线程可以具有以下任何一种状态:
- 中止 - 线程已死但未停止
- 运行 - 线程正在执行
- 停止 - 线程已停止执行
- 暂停 - 线程已暂停
- Unstarted - 线程已创建但尚未开始执行
- WaitSleepJoin – 线程调用 sleep,在另一个对象上调用 wait,并在其他线程上调用 join
问题:为什么我们在 C# 中使用 Async 和 Await?
答:属于异步编程的进程独立于主进程或其他进程运行。在 C# 中,使用 Async 和 Await 关键字来创建异步方法。
C#常见面试题有哪些:什么是 C# 中的索引器,你如何创建索引器?
答:也称为索引属性,索引器是一个类属性,允许使用数组的特性访问某个类的成员变量。用于将对象视为数组,索引器允许更直观地使用类。虽然索引器不是面向对象编程的重要组成部分,但它是使用数组的一种巧妙方式。因此,它们也被称为智能阵列。定义索引器可以创建类似于虚拟数组的类。可以使用 [] 数组访问运算符访问此类类的实例。在 C# 中创建索引器的一般语法是:
< modifier > <
return type > this[argument list] {
get {
// the get block code
}
set {
// the set block code
}
}
问题:C# 中的竞态条件是什么?
答:当两个线程访问同一个资源并尝试同时更改它时,我们会遇到竞争条件。几乎不可能预测哪个线程首先成功访问了资源。当两个线程尝试将值写入同一资源时,会保存最后写入的值。
问题:你对Get 和Set Accessor 属性的理解是什么?
答:使用属性制作,Get 和 Set 在 C# 中称为访问器。属性允许读取和写入私有字段的值。访问器用于访问此类私有字段。我们使用 Get 属性返回属性值,而使用 Set 属性设置值。
问题:详细解释ref和out关键字的区别。
答:在任何 C# 函数中,都可以有三种类型的参数,即 in、out 和 ref。尽管 out 和 ref 在运行时受到不同的对待,但它们在编译时受到相同的对待。不能将属性作为 out 或 ref 参数传递。以下是 ref 和 out 关键字之间的区别:
- 初始化参数或参数——虽然在传递给输出参数之前初始化参数或参数不是强制性的,但在将其传递给 ref 参数之前同样需要初始化。
- 初始化参数的值——在返回调用方法之前,使用 ref 不需要分配或初始化参数的值。然而,当使用 out 时,在返回到调用方法之前,必须使用被调用的方法来分配或初始化参数的值。
- 有用性——当被调用的方法需要修改传递的参数时,通过 Ref 传递参数值是有用的。当需要从函数或方法返回多个值时,向 out 方法声明参数是合适的。
- 在调用方法中初始化参数值——在调用方法中初始化参数值是一种在使用时的强制。但是,在使用 ref 参数时同样是可选的。
- 数据传递——使用 out 允许仅以单向方式传递数据。但是,使用 ref 时可以双向传递数据。
C#常见面试问题和答案合集:什么是 C# 中的单例设计模式?用一个例子解释它们的实现。
答:C# 中的单例是一个类,它只允许创建自身的单个实例并提供对该唯一实例的简单访问。因为具有不同参数的实例的第二个请求可能会导致问题,所以单例通常不允许指定任何参数。以下示例演示了单例设计模式在 C# 中的实现:
namespace Singleton {
class Program {
static void Main(string[] args) {
Calculate.Instance.ValueOne = 10.5;
Calculate.Instance.ValueTwo = 5.5;
Console.WriteLine("Addition : " + Calculate.Instance.Addition());
Console.WriteLine("Subtraction : " + Calculate.Instance.Subtraction());
Console.WriteLine("Multiplication : " + Calculate.Instance.Multiplication());
Console.WriteLine("Division : " + Calculate.Instance.Division());
Console.WriteLine("\n----------------------\n");
Calculate.Instance.ValueTwo = 10.5;
Console.WriteLine("Addition : " + Calculate.Instance.Addition());
Console.WriteLine("Subtraction : " + Calculate.Instance.Subtraction());
Console.WriteLine("Multiplication : " + Calculate.Instance.Multiplication());
Console.WriteLine("Division : " + Calculate.Instance.Division());
Console.ReadLine();
}
}
public sealed class Calculate {
private Calculate() {}
private static Calculate instance = null;
public static Calculate Instance {
get {
if (instance == null) {
instance = new Calculate();
}
return instance;
}
}
public double ValueOne {
get;
set;
}
public double ValueTwo {
get;
set;
}
public double Addition() {
return ValueOne + ValueTwo;
}
public double Subtraction() {
return ValueOne - ValueTwo;
}
public double Multiplication() {
return ValueOne * ValueTwo;
}
public double Division() {
return ValueOne / ValueTwo;
}
}
}
单例设计模式确保一个类只有一个实例,并提供一个全局访问点。在 C# 中有多种实现单例设计模式的方法。以下是单例模式的典型特征:
- 获取对创建的单个实例的引用的公共静态方法
- 单个构造函数,私有且无参数
- 一个静态变量,持有对创建的单个实例的引用
- class被封
结论
这总结了面向经验丰富的专业人士和初学者的顶级 c# 面试问题列表。你已经知道了多少个答案?通过评论告诉我们。查看这些最佳 C# 教程以进一步增强你对 C# 的理解。