专业编程基础技术教程

网站首页 > 基础教程 正文

C#面试宝典 2022年 60个常见的C#面试问题和答案

ccvgpt 2024-12-02 15:43:50 基础教程 8 ℃

我们整理了60个常见的C#面试问题和答案,包括初级,中级和高级面试问题。对即将参加面试的同学非常有用,建议收藏研读。


C#面试宝典 2022年 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 注释的一个示例是:///概括///这里可以写任何东西///概括


Code with Mosh - 通过编码学习 C# 基础知识


https://www.koudaizy.com/tutorials/csharp-tutorial-for-beginners/


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.什么是多态性?


多态意味着相同的方法但不同的实现。有两种类型的多态性。


  1. 编译时多态性是通过方法重载实现的,如下例所示。


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");
        }
}


  1. 运行时多态性是通过方法覆盖来实现的,如下例所示。


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”不能与静态类一起使用,因为我们只能在静态类中使用静态变量和静态方法。


学习C#课程:Udemy 完整 C# 大师班


https://www.koudaizy.com/tutorials/complete-csharp-masterclass/


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);
        }
    }
}


学习Udemy付费课程:C# 和 .NET 中的设计模式


https://www.koudaizy.com/tutorials/design-patterns-csharp-dotnet/


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 操作阻塞线程。


面向初学者的 C# 编程:第一步


https://www.koudaizy.com/tutorials/c-programming-a-practical-applications-approach/


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# 中创建的所有类的父类是哪个?


这是一个简单的问题:系统对象。


面向初学者的终极 C# 和 Unity 课程


https://www.koudaizy.com/tutorials/ultimate/


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#,口袋资源编程训练营或进修课程会有所帮助。

Tags:

最近发表
标签列表