我们整理了60个常见的C#面试问题和答案,包括初级,中级和高级面试问题。对即将参加面试的同学非常有用,建议收藏研读。
许多雇主对只会纸上谈兵的程序员都保持持谨慎态度,特别是没有编程经验但而有学位的人。正因为如此,他们经常在面试中提出深入的编程问题。如果你没有做好充分的准备,这些问题可能很难回答。
在本文中,我将帮助你准备好在下一次面试中解决这些与C# 编程语言相关的问题。同时,你可能想练习一些C# 项目。这 60 个基本的 C#面试问题和答案将帮助你了解该语言的技术概念。
什么是 C#?
C# 于 2000 年发布,是一种基于 C 的编程语言,用于从桌面应用程序到 Web 服务的所有内容。今天,C# 是世界上最流行的编程语言之一,它是一种在编程领域备受追捧的语言。
C# 在几个主要方面与 C++不同。最明显的是,C# 是一种基于组件的语言,而 C++ 是一种面向对象的语言。C# 被认为比 C++ 更重量级,但它被用于许多现代系统,例如游戏开发工具包。
初学者 C# 面试问题和答案
1.什么是类?
类是创建对象的模板。它包含属性和方法。我们可以从一个类创建许多对象实例。
下面是一个类的例子:
public class Student
{
//data members
public int rollNumber { get; set; }
public string fullName { get; set; }
//function
public void PrintDetails()
{
//login of function
}
}
2.面向对象编程的主要概念是什么?
封装、抽象、多态和继承是面向对象编程的主要概念。准备好描述其中的每一个。面向对象编程与过程编程的不同之处在于过程编程按时间顺序、逐步进行,而面向对象编程则灵活得多。
3.什么是对象?
对象是一个类的实例,我们通过它访问该类的功能。我们可以使用“new”关键字来创建一个对象。在内存中创建对象的类保存有关该类的函数、数据成员和行为的信息。
请参阅下面的对象语法。
//Class
public class Employee
{
//private members
private string fName { get; set; }
private string lName { get; set; }
//function
public void Display()
{
Console.WriteLine("Full name is {0} {1}", fName, lName);
}
public void SetName(string firstName, string lastName)
{
fName = firstName;
lName = lastName;
}
}
class Program
{
static void Main(string[] args)
{
//this is object
Employee employee = new Employee();
employee.SetName("John", "Grande");
employee.Display();
}
}
4.什么是构造函数,它有哪些不同的类型?
构造函数就像一个与类同名的方法,但它是唯一的方法。即使没有创建,编译器也会在创建类的对象时在内存中创建一个默认构造函数。构造函数用于使用一些默认值初始化对象。默认构造函数、参数化构造函数、复制构造函数、静态构造函数和私有构造函数都是不同的构造函数类型。
下面是不同构造函数类型的示例。
public class Student
{
private int rollNumber { get; set; }
private string fullName { get; set; }
//default constructor
public Student()
{
//code goes here
}
//parameterized constructor
public Student(int rNum, string fName)
{
this.rollNumber = rNum;
this.fullName = fName;
}
//static constructor
static Student()
{
//code goes here
}
//copy constructor
public Student(Student student)
{
rollNumber = student.rollNumber;
fullName = student.fullName;
}
}
5. C#中的析构函数是什么?
析构函数清除内存以释放资源,并由垃圾收集器自动管理。为此目的在内部调用 System.GC.collect()。但是,如果需要,可以使用析构函数显式完成。
public class Purchase
{
//Syntax to write a destructor.
~Purchase()
{
//code here to release resources.
}
}
6. C# 代码是托管代码还是非托管代码?
C# 是托管代码,因为公共语言运行时将代码编译为中间语言代码。C++ 将提供非托管代码的示例。托管代码只是指其执行由运行时管理的代码。
7.什么是值类型和引用类型?
我们可以将变量分为值类型和引用类型。值类型变量直接包含值,而引用类型变量包含内存地址的引用,其中值实际存储在内存中。Bool、byte、int、char 和 decimal 是值类型。字符串、类、委托都是引用类型。
8.什么是命名空间,它是强制性的吗?
命名空间是一种以相同名称组织相同组或功能的类的方法。我们可以称它为模块。尽管将类放在命名空间中并不是强制性的。
请参阅下面的语法。
namespace demoapp
{
class SomeClass
{
public static void someMethod()
{
Console.WriteLine("Creating my namespace");
}
}
}
9.用例子解释 C# 中的注释类型
C# 中有三种类型的注释。
- 单行注释
- 多行注释
- XML 注释
单行注释的示例是://嘿,这是单行注释
多行注释的一个例子是:/*这是一个多行注释写成两行*/
XML 注释的一个示例是:///概括///这里可以写任何东西///概括
10.请解释封装
封装是将函数和数据成员包装在一个类中的过程;它就像一个胶囊,一个单一的单元。封装可防止来自函数外部的未经授权或不需要的数据更改。它用于更好地控制和标准化你的代码。下面是一个封装的例子。
class User
{
private string address;
private string name;
public string Address
{
get
{
return address;
}
set
{
address = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyProgram
{
static void Main(string[] args)
{
User u = new User();
// set accessor will invoke
u.Name = "Ravi";
// set accessor will invoke
u.Address = "New Delhi";
// get accessor will invoke
Console.WriteLine("Name: " + u.Name);
// get accessor will invoke
Console.WriteLine("Location: " + u.Address);
Console.WriteLine("nPress Enter Key");
Console.ReadLine();
}
}
11.什么是抽象?
抽象是只暴露类的必需特性并隐藏不必要信息的方法。我们可以尝试以摩托车为例来理解它:骑手知道自行车的颜色、名称和型号。尽管如此,他们仍然不了解内部发动机和排气功能。同样,抽象侧重于提供对特定功能的访问,而不暴露该功能在内部是如何工作的。
12.什么是多态性?
多态意味着相同的方法但不同的实现。有两种类型的多态性。
- 编译时多态性是通过方法重载实现的,如下例所示。
public class cellphone
{
//function with the same name but different parameters.
public void Typing()
{
Console.WriteLine("Using keypad");
}
public void Typing(bool isSmartPhone)
{
Console.WriteLine("Using qwerty keyboard");
}
}
- 运行时多态性是通过方法覆盖来实现的,如下例所示。
public class CellPhone
{
public virtual void Typing()
{
Console.WriteLine("Using keypad");
}
}
public class SmartPhone : CellPhone
{
//method override
public override void Typing()
{
Console.WriteLine("Typing function from child class");
}
}
13.定义一个界面并展示一个例子。
接口是抽象类的另一种形式,它只有抽象的公共方法。这些方法只有声明,没有定义。实现接口的类必须实现接口的所有方法。
例如:
interface IPencil
{
void Write(string text);
void Sharpen(string text);
}
class Pencil : IPencil
{
public void Write(string text)
{
//some code here
}
public void Sharpen(string text)
{
//some code here
}
}
public class CellPhone
{
public virtual void Typing()
{
Console.WriteLine("Using keypad");
}
}
14.什么是继承?
一个类可以从另一个类(称为其父类)继承数据成员和方法。继承属性和方法的类将被称为子类、派生类。派生类中的某些属性可以被覆盖。从类继承特征的能力使管理类的整个过程变得更加容易,因为你可以创建自定义的子类。原始类将被称为父类或基类。
请参考以下示例:
class Mobile // base class (parent)
{
public void call()
{
Console.WriteLine("calling...!");
}
}
class Nokia : Mobile // derived class (child)
{
public string modelName = "Nokia";
}
class MyProgram
{
static void Main(string[] args)
{
// Create a myNokia object
Nokia myNokia = new Nokia();
// Calls the call() method (From the Mobile class) on the myNokia object
myNokia.call();
}
}
中级 C# 编程问题
15.如何在同一个类中实现多个具有相同方法名的接口?
要实现具有相同方法名称的多个接口,你将避免在函数体中实现。相反,你将显式地将接口名称提供给方法的主体。编译器将了解所引用的接口方法,从而解决问题。
这可以在以下示例中看到:
interface myInterface1
{
void Print();
}
interface myInterface2
{
void Print();
}
class Student : myInterface1,
myInterface2
{
void myInterface1.Print()
{
Console.WriteLine("For myInterface1 !!");
}
void myInterface2.Print()
{
Console.WriteLine("For myInterface2 !!");
}
}
16.什么是虚方法,它与抽象方法有什么不同?
一个虚方法必须有一个默认实现,我们可以在派生类中使用 override 关键字来覆盖这个虚方法。抽象方法没有实现,只在抽象类内部创建。在抽象类的情况下,从抽象类派生的类必须具有该抽象方法的实现。
下面是一个虚方法的例子:
public class CellPhone
{
public virtual void Typing()
{
Console.WriteLine("Using old keypad");
}
}
public class SmartPhone : CellPhone
{
public override void Typing()
{
Console.WriteLine("Using qwerty keyboard");
}
}
下面是一个抽象方法的例子:
public abstract class CellPhones
{
//no default implementation
public abstract void Typing();
}
public class OldPhones : CellPhones
{
//function override
public override void Typing()
{
Console.WriteLine("Using keypad");
}
}
public class SmartPhones : CellPhones
{
//function override
public override void Typing()
{
Console.WriteLine("Using Qwerty keyboard");
}
}
17.什么是方法重载和方法覆盖?
方法重载和覆盖都是一种多态性。
- 方法重载是指我们有一个名称相同但签名不同的函数。
- 方法覆盖是当我们使用 override 关键字覆盖子类中基类的虚拟方法时。
18.什么是static关键字?
我们使用 static 关键字来创建静态类、静态方法或静态属性。当我们创建一个静态类时,该类中只能有静态数据成员和静态方法。静态意味着我们不能创建该类的实例。该类可以像 ClassName.methodName 一样直接使用。当需要其他类的所有实例都具有的特殊功能时,我们使用静态类。例如,需要加载一些默认的应用程序级值。我们创建一个带有静态函数的静态类。然后,所有其他类都可以访问该类,而无需创建任何实例。它还与所有类共享相同的数据。
请参考以下示例:
public static class Setting
{
public static int fetchDefault()
{
int maxAmount = 0;
//code to fetch and set the value from config or some file.
return maxAmount;
}
}
public class Sales
{
//not required to create an instance.
int maxAmount = Setting.fetchDefault();
}
19.我们可以在静态类中使用“this”吗?
不可以。“this”不能与静态类一起使用,因为我们只能在静态类中使用静态变量和静态方法。
20.常量和只读变量有什么区别?
有几点不同:
- 常量变量只能在声明时赋值,我们不能在整个程序中更改该变量的值。
- 我们可以在声明时或在同一类的构造函数中将值分配给只读变量。
下面是一个常量示例:
using System;
namespace demoapp
{
class DemoClass
{
// Constant fields
public const int myvar = 101;
public const string str = "staticstring";
// Main method
static public void Main()
{
// Display the value of Constant fields
Console.WriteLine("The value of myvar: {0}", myvar);
Console.WriteLine("The value of str: {0}", str);
}
}
}
下面是一个只读示例:
using System;
namespace demoapp
{
class MyClass
{
// readonly variables
public readonly int myvar1;
public readonly int myvar2;
// Values of the readonly
// variables are assigned
// Using constructor
public MyClass(int b, int c)
{
myvar1 = b;
myvar2 = c;
Console.WriteLine("Display value of myvar1 {0}, " +
"and myvar2 {1}", myvar1, myvar2);
}
// Main method
static public void Main()
{
MyClass obj1 = new MyClass(100, 200);
}
}
}
21. C#中的string和string builder有什么区别?
字符串是不可变的对象。当我们必须执行一些操作来更改字符串或附加新字符串时,它会清除字符串对象的旧值,并在内存中创建一个新实例以将新值保存在字符串对象中。
例如,它使用 System.String 类。
using System;
namespace demoapp
{
class StringClass
{
public static void main(String[] {
string val = "Hello";
//creates a new instance of the string
val += "World";
Console.WriteLine(val);
}
}
}
StringBuilder 是一个可变对象,这意味着它每次都会为添加字符串(追加),替换字符串(替换)等操作创建一个新实例。它仅将旧对象用于对字符串执行的任何操作,从而提高性能。
例如,它使用 System.Text.StringBuilder 类。
using System;
using System.Text;
namespace demoapp
{
class StringClass
{
public static void main(String[] {
StringBuilder val = new StringBuilder("Hello");
val.Append("World");
Console.WriteLine(val);
}
}
}
两个程序的输出都是一样的,“Hello World”。
22.解释“continue”和“break”语句。
我们可以在 C# 的循环中使用 continue 和 break 语句。使用 break 语句,我们可以中断循环执行,而使用 continue 语句,我们可以中断循环的一次迭代。
下面是一个 break 语句的例子:
using System;
namespace demoapp
{
class LoopingStatements
{
public static void main(String[] args)
{
for (int i = 0; i <= 5; i++)
{
if (i == 4)
{
break; //this will break the loop
}
Console.WriteLine("The number is " + i);
Console.ReadLine();
} //control will jump here after the break statement.
}
}
}
这是带有 continue 语句的相同示例:
using System;
namespace demoapp
{
class LoopingStatements
{
public static void main(String[] args)
{
for (int i = 0; i <= 5; i++)
{
if (i == 4)
{
continue;// it will skip the single iteration
}
Console.WriteLine("The number is " + i);
Console.ReadLine();
}
}
}
}
23. 什么是装箱和拆箱?
值类型数据类型到引用类型(对象)数据类型的转换称为装箱。
例如:
namespace demoapp
{
class Conversion
{
public void DoSomething()
{
int i = 10;
object o = i;
}
}
}
拆箱是将引用类型数据类型转换为值类型。
例如:
namespace demoapp
{
class Conversion
{
public void DoSomething()
{
object o = 222;
int i = (int)o;
}
}
}
24.什么是密封类?
我们使用“sealed”关键字来创建一个密封类。当不需要进一步继承或需要限制该类被继承时,类被创建为密封类。请参阅下面的语法。
public sealed class MyClass
{
//properties and methods
}
25.什么是偏类?
C# 语言中有一个特性是将单个类文件分成多个物理文件。为此,我们必须使用“partial”关键字。在编译时,它在逻辑上只是一个文件;我们不能在两个不同的分部类文件中拥有同名的方法或同名的变量。 在这里,为了方便开发者将大类文件分解成多个小的物理文件,提供了这个功能。
26.什么是枚举?
“枚举”关键字在许多语言中都很常见。枚举是一种值。它用作相关常量的集合,称为枚举列表。 枚举可以是 int、float、double 或 byte。但如果它不是 int,则需要显式转换。.NET 框架枚举可用于创建数字常量。Int 是枚举元素的默认值。默认情况下,第一个枚举数的值为 0,并且每个后续的枚举数都增加 1,就像一个数组一样。请参考以下语法:enum Day { Sat, Sun, Mon, Tue, Wed, Thu, Fri };
27.什么是依赖注入,如何实现?
依赖注入是一种设计模式。我们不是直接在另一个类(依赖类)中创建一个类的对象,而是将对象作为参数传递给依赖类的构造函数。它有助于编写松散耦合的代码,并有助于使代码更加模块化和易于测试。实现依赖注入的三种方式:
- 构造函数注入:这是最常用的注入类型。在构造函数注入中,我们可以将依赖项传递给构造函数。我们必须确保这里没有默认构造函数,唯一的应该是参数化构造函数。
- 属性注入:在某些情况下,我们需要一个类的默认构造函数,那么在这种情况下,我们可以使用属性注入。
- 方法注入:在方法注入中,我们只需要在方法中传递依赖即可。当整个类不需要那个依赖时,就不需要实现构造函数注入。当我们对多个对象有依赖关系时,我们不会在构造函数中传递该依赖关系,而是在需要它的函数本身中传递该依赖关系。
28.请解释“using”语句。
关键字“using”用于定义该 using 语句块中使用的资源的范围。一旦代码块完成执行,在 using 代码块中使用的所有资源都会被释放。
请参考以下示例。
class Books : IDisposable
{
private string _name { get; set; }
private decimal _price { get; set; }
public Books(string name, decimal price)
{
_name = name;
_price = price;
}
public void Print()
{
Console.WriteLine("Book name is {0} and price is {1}", _name, _price);
}
public void Dispose()
{
throw new NotImplementedException();
}
}
class Students
{
public void DoSomething()
{
using (Books myBook = new Books("book name", 12.45))
{
myBook.Print();
}
}
}
29.什么是访问修饰符?解释每种类型。
访问修饰符是用于提供对类、成员或函数的可访问性的关键字。以下是它的类型:
- Public:可以在任何地方访问,没有任何限制
- Protected:访问仅限于继承该类的类
- Internal:只能在当前程序集中访问
- Private:外部无法访问
访问修饰符的语法:
public class Product
{
public void Print()
{
//code to print something.
}
}
30.什么是C#委托?
委托就像函数指针,它是一个引用数据类型,保存着方法的引用。我们使用委托来编写泛型类型安全函数。所有委托都派生自 System.Delegate。可以使用 delegate 关键字后跟函数签名来声明委托,如下所示。这些是代表的特征:
- 委托派生自 System.Delegate 类
- 代表具有签名和返回类型。分配给代表的函数必须符合此签名
- 代表可以指向实例方法或静态
- 委托对象一旦创建,就可以在运行时动态调用它所指向的方法
- 委托可以同步和异步调用方法
请参考以下示例:
using System;
namespace demoapp
{
class DelegateClass
{
// declare delegate
public delegate void Print(int value);
static void Main(string[] args)
{
// Print delegate points to PrintNumber
Print printDel = PrintNumber;
// or
// Print printDel = new Print(PrintNumber);
printDel(100000);
printDel(200);
// Print delegate points to PrintMoney
printDel = PrintMoney;
printDel(10000);
printDel(200);
}
public static void PrintNumber(int num)
{
Console.WriteLine("Number: {0,-12:N0}", num);
}
public static void PrintMoney(int money)
{
Console.WriteLine("Money: {0:C}", money);
}
}
}
31.委托有哪些不同类型?
代表分为三种类型:
- 单个委托可以调用单个方法
- 多个委托可以调用多个方法。委托方法可以进行多播。我们可以使用 + 运算符在委托实例中添加一个方法,也可以使用 – 运算符删除一个方法。所有方法在分配时按顺序调用。
- .Net Framework 3.5 引入了通用委托。无需在通用委托中创建实例。
32.什么是数组?解释一维和多维数组。
该数组存储相同类型的值。它是将变量存储到内存位置的集合。
例如:
int[] marks = new int[3] { 25, 34, 89 };
一维数组是线性数组。一维数组将变量存储在一行中。上面的例子是一个一维数组。数组可以有多个维度。多维数组也称为矩形数组。
例如:
int[,] numbers = new int[3, 2] { { 1, 2 }, { 2, 3 }, { 3, 4 } };
33. System.Array.CopyTo() 和 System.Array.Clone() 有什么区别?
使用 Clone() 方法,我们可以使用 CopyTo() 方法创建一个包含原始数组的所有元素的新数组对象。现有数组的所有项目都复制到另一个现有数组中。两种方式都会创建一个浅拷贝。
34.Array和ArrayList有什么区别?
Array和 ArrayList 类似。当你想存储相同类型的项目时,可以使用Array。Array具有固定大小。当你要存储任何类型的数据时,我们使用 ArrayList。ArrayList 没有固定大小。
参考数组和ArrayList的例子:
using System.Collections;
namespace demoapp
{
class Sample
{
//Array and Araraylist.
public void ArrayFunction()
{
string[] country = new string[3];
country[0] = "USA"; //only string value can be added
country[1] = "Denmark";
country[2] = "Russia";
//can store different data types
ArrayList arraylist = new ArrayList();
arraylist.Add(3);
arraylist.Add("USA");
arraylist.Add(false);
}
}
}
35.什么是C#中的交错数组?
交错数组就像一个嵌套数组,其中交错数组的每个元素本身就是一个数组。锯齿状数组的项目可以具有不同的维度和大小。锯齿状数组是 C# 中引入的一种特殊类型的数组。锯齿状数组是数组的数组,其中每个数组索引的长度可以不同。
请参考以下示例:
namespace demoapp
{
public class JaggedArrayClass
{
public void ShowJaggedArray()
{
int[][] jaddedArray = new int[2][];
jaddedArray[0] = new int[3] { 1, 2, 3 };
jaddedArray[1] = new int[4] { 1, 2, 3, 4 };
}
}
}
36. struct和class有什么区别?
类和结构体都是用户定义的,但有很大的不同。struct 继承自 System.Value 类型,因此它是值类型。当数据量较小时,结构体更可取。结构不能是抽象的。无需使用 new 关键字创建对象。Struct 无权创建任何默认构造函数。
结构的语法:
struct MyStruct
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
}
类是 C# 中的引用类型,它继承自 System.Object 类型。当有大量数据时,使用类。我们可以从另一个类继承一个类。类可以是抽象类型。
37. “throw”和“throw ex”有什么区别?
“throw”语句将保留前一个函数的原始错误堆栈,而“throw ex”语句将保留从抛出点开始的堆栈跟踪。通常,建议使用“throw”,因为它提供了准确的错误信息和跟踪数据。
38.解释“finally”和“finalize block”的区别?
这是两个不同的概念,尽管它们听起来很相似:
- 最后是执行处理的代码块部分。无论是否发生异常,此代码块都会执行。
- Finalize 是在垃圾回收之前调用的方法。当没有在代码中显式调用时,编译器会自动调用此方法。
因此,finally 与执行处理有关,而 finalize 与垃圾收集有关。
39.解释 var 和 dynamic。
我们可以声明变量的 var 类型,而无需明确指定 .net 数据类型。编译器在编译时根据分配给它的值自动检测变量的类型。我们不能声明一个 var 类型的变量而不给它赋值。var 类型变量的值不能在后面的代码中更改。动态与var相反。
稍后我们可以在代码中更改动态类型变量的值。它还根据分配给它的值决定变量的类型。 就像在创建动态类型的变量时,会为其分配一个整数类型的值,然后在进一步的代码中,我们可以为该变量分配一个字符串类型的值。它保存最后更改的值,其行为类似于它保存的最新值的数据类型。
让我们看这个例子来更详细地理解它。
public class Bike
{
dynamic someValue = 21;
public Bike()
{
//assigned string value later
someValue = "Hello";
}
}
在上面的示例中,如果我们将变量“someValue”声明为 var 而不是 dynamic,则会引发错误。该错误的原因是在下一行中,我们更改了变量的值并分配了一个字符串值。
高级 C# 编程问题
40. C# 中的匿名类型是什么?
有时我们可能需要创建一个新类型而不定义它。这将被称为匿名类型。当需要在单个对象中定义只读属性而不定义每种类型时,这很有用。 在这里,编译器生成类型并且只能用于当前代码块。
请参考以下示例。
public class SomeClass
{
public void print()
{
var anonymousData = new
{
FirstName = "John",
SurName = "lastname"
};
Console.WriteLine("First Name : " + anonymousData.FirstName);
}
}
41. 什么是多线程,它有哪些不同的状态?
C# 中的任何代码块都在称为线程的进程中运行。线程是程序的执行路径。简单的应用程序可以在单线程上运行,但今天的程序经常使用多线程。多线程将进程的执行划分为多个线程以同时执行它,从而提高效率。 通过多线程,我们可以一次运行多个任务。程序更高效、更快捷。但是我们还需要了解线程是如何工作的。每个线程都有自己的生命周期,其中包括线程的各种状态:
- 未启动状态:在这种状态下,编译器创建线程的实例但等待启动方法。
- 已启动:是线程准备好运行并等待 CPU 周期时的状态。
- 不可运行状态:线程在以下情况下不可执行。
- 当我们调用“睡眠”或“等待”方法时。
- I/O 操作阻塞线程。
42. C#中的异常处理是如何完成的?
异常处理通过 try、catch、finally 和 throw 模型进行管理。这些是整个模型中使用的关键字。下面是每个关键字的解释:
- Try:我们将代码保存在我们想要处理异常的 try 块中。
- Catch:当 try 块中发生任何异常时,在异常处理程序的帮助下将其捕获到 catch 块中。
- finally:为了不考虑错误地执行代码块,我们将该代码放在 finally 块中以执行。
- Throw:发生问题时抛出异常。
下面是异常处理的例子:
public class SomeClass
{
public void GetData()
{
try
{
//write some code here
}
catch (Exception)
{
throw;
}
finally
{
/*code to execute in the last
like dispose objects and resource*/
}
}
}
43.什么是自定义异常?
自定义异常用于根据用户要求捕获的错误,而不是内置在编译器中的错误。自定义异常是实例化用户定义异常的一种简单方法。
请参考以下示例:
public class Purchase
{
public void DoPurchase(int quantity)
{
if (quantity == 0)
{
//this will throw error here with the custom message
throw new Exception("Quantity cannot be zero");
}
}
}
44.什么是 C# 中的 LINQ?
LINQ 是指语言集成查询。LINQ 是一种使用 .NET 功能和类似于 SQL 的 C# 语法查询数据的方法。 LINQ 的优点是我们可以查询不同的数据源。数据源可以是对象的集合、XML 文件、JSON 文件、内存中的数据或列表或数据库对象。我们可以轻松地从任何实现 IEnumerable<T> 接口的对象中检索数据。
下面是 LINQ 的语法
public class Devices
{
public void GetData()
{
List<string> mobiles = new List<string>() {
"Iphone","Samsung","Nokia","MI"
};
//linq syntax
var result = from s in mobiles
where s.Contains("Nokia")
select s;
}
}
45.什么是序列化?
当我们想通过网络发送一个对象时,我们必须将该对象转换为字节流。序列化是将对象转换为字节流的过程。为了便于对象进行可序列化,它应该实现 ISerialize 接口。反序列化的过程是从字节流创建对象的逆过程。
46. C#中的泛型是什么?
C# 中的泛型:
- 提高性能。
- 增加类型安全。
- 减少重复代码。
- 制作可重用的代码。
使用泛型,我们可以创建集合类。最好使用 System.Collections.Generic 命名空间而不是 System.Collections 命名空间中的类(例如 ArrayList)来创建泛型集合。泛型鼓励使用参数化类型,
如下例所示:
using System;
namespace demoapp
{
//We use < > to specify Parameter type
public class GFG<T>
{
//private data members
private T data;
//using properties
public T value
{
/using accessors
get
{
return this.data;
}
set
{
this.data = value;
}
}
}
//vehicle class
class Vehicle
{
//Main method
static void Main(string[] args)
{
//instance of string type
GFG<string> company = new GFG<string>();
company.value = "Tata motors";
//instance of float type
GFG<float> version = new GFG<float>();
version.value = 6.0F;
//display Tata motors
Console.WriteLine(company.value);
//display 6
Console.WriteLine(version.value);
}
}
}
47.什么是反射(Reflection)?
Reflection 是 C# 中的一个特定类,用于访问程序集或类的元数据。可以使用反射检索以下信息:
- Assembly name
- Class name
- Method name
- Object type
- It Identifies properties and methods.
48.如何使用可空类型?
空值可以分配给 C# 中的变量。这些类型称为可空类型。大多数变量类型都是可为空的类型。
下面的例子:
namespace demoapp
{
class Calculate
{
int? number = null;
public Calculate(int num)
{
number = num;
}
public void DoCalculation()
{
if (number.HasValue)
{
//do something
}
}
}
}
49.我们在 C# 中创建的所有类的父类是哪个?
这是一个简单的问题:系统对象。
50.解释 C# 中的代码编译。
程序员编写人们可读的代码。然后将该代码输入 C# 编译器。C# 编译器会将代码编译成高效、机器可读的托管代码,称为字节码。然后,即时编译器 (JIT) 会将字节码编译为本机或机器语言。当程序运行时,CPU会直接执行这段代码。
51.什么是 C# 中的哈希表?
哈希表通常包含“键”和“值”。你经常会听到关于密码的“哈希表”;可以为给定的密码创建密码哈希。但是哈希表本身只是键对象和值对象的通用集合,其中的值必须使用键来访问;否则无法访问它们。
52. 如何从基类创建派生类对象?
这是一个技巧问题!你不能。派生类将从基类继承变量和方法。此外,派生类只能有一个基类。你需要直接使用基类进行工作。
53.什么是不可变字符串?
不可变字符串是不能更改的对象,尽管你可以更改对它的引用。通常,只要你有绝对不应该更改的常量,就应该使用不可变字符串。但是,你应该谨慎使用此技巧,因为如果你稍后尝试更改不可变字符串,它可能会引发错误。
54.什么是C#中的反射?
反射是指系统能够查看和修改自身的方法和过程。在 C# 中,反射是指检查系统的内容。它需要通过“System.Reflection”命名空间手动包含在 C# 中。反射对于调试工具特别有用。
55.什么是泛型类?
泛型类是可以处理任何类型的类。这是独一无二的,因为大多数类都遵循严格的类型;你必须声明一个类型,并且该类型必须是一致的。
定义一个泛型类如下:
class dataStore<T> {
public T data {
get; set;
}
}
56.什么是params关键字,如何使用?
通过使用 params 关键字,你可以指定采用可变数量参数的方法参数。参数类型必须是一维数组。
public static void CalcListSum(params int[] list)
{
int sum =0
for (int i = 0; i < list.Length; i++)
{
sum+=list[i];
}
Console.WriteLine("The sum is " + sum);
}
57. 什么是 NuGet?
NuGet 是面向开发人员的包管理器。它使开发人员能够共享和使用有用的代码。NuGet 包是单个 ZIP 文件,带有 .nupack 或 .nupkg 文件扩展名,并包含 .NET 程序集及其所需文件。
58、什么是DLL文件,使用它们有什么好处?
DLL 是一个库,其中包含可由多个程序同时使用的代码和数据。每个程序都可以使用 DLL 中包含的功能。这有助于提高代码的可重用性和有效的内存使用。通过使用 DLL,可以将程序模块化为单独的组件。
因为模块是分开的,所以程序的加载时间更快。并且仅在请求该功能时才加载模块。此外,更新更容易应用于每个模块,而不会影响程序的其他部分。当这些更改被隔离到 DLL 时,你可以应用更新而无需再次构建或安装整个程序。
59. POCO 是什么意思?
POCO 代表普通旧 CLR 对象。POCO 是一个不依赖于任何特定于框架的基类的类。它与任何其他普通的 .NET 类一样。因此名称为普通旧 CLR 对象。这些 POCO 实体(也称为持久性忽略对象)支持大多数与实体对象派生实体相同的 LINQ 查询。
60. 什么是 DTO?
数据传输对象(通常称为 DTO)通常是 POCO(普通旧 CLR 对象)类的实例,用作封装数据并将其从应用程序的一层传递到另一层的容器。你通常会发现在服务层(后端)中使用 DTO 将数据返回到表示层(前端)。
总结
参考上述问题和答案,可以让我们深入了解 C# 语言的所有基本概念。这些技术性的答案有助于提高我们的知识,并有助于增加我们对语言的理解。如果你需要复习 C#,口袋资源编程训练营或进修课程会有所帮助。
如果本站的内容对你有帮助,可以点击这儿,不花一分钱捐赠本站