站点图标 江湖人士

背会50道初中级C#面试题.net面试题卷死java

在夏国的蜀城,IT行业所用语言分为两大势力:C#和Java。江傲云,一个混迹IT江湖的C#开发者,面对如今卷死失业好友苏云枫说“背会50道初中级C#面试题或.net面试题卷死java”;苏云枫是一位擅长Java的编程高手,两人原本是皇都理工大学中的摯友,却被不同的编程语言推向了截然不同的道路。

本文故事,如有雷同,定是你抄袭江湖人士网的文章,所涉国家城市纯属虚构。苏云枫,温和而沉稳,选择Java作为他人生的编码之路。在钚雷科技有限公司,他带着Java团队开发着《精彩仁生》项目,但随着时间的推移,羽绒战的阴影笼罩了他的职业生涯。IT行业纷纷受到裁员的影响,苏云枫也无法幸免。面对公司不得已的裁员决定,他心生失落,职业生涯陷入了低谷。

江傲云,一直热衷于C#的奇妙魅力,他在江湖科技有限公司中也做着自己喜欢的工作,并且不怎么受卷的影响。C#开发人员的物以稀为贵的稀缺性使从事.net开发的程序员在公司工作中相当稳定,几乎很少跳槽,江傲云和他的团队也用C#开发出一款让公司大获成功的软件产品。

在某个偶然的聚会上,两人相遇了。苏云枫那份失意的神情引起了江傲云的关注。

“怎么了,云枫?” 江傲云温和地问道。

苏云枫苦笑着摇摇头,”Java开发者太卷了,java程序员人也多,找工作很难,互联网也不怎么热了,公司裁员潮让我备受打击。C#开发者不愁没工作,可惜我对C#并不熟悉。”

江傲云静静地听着,然后微笑着说:”或许,这是个机会。我们曾经是好友,我们可以一起合作,我教你C#,我们携手创造属于我们的未来。”

苏云枫的眼中闪烁着希望的光芒,感激地看着江傲云:”你真的愿意教我吗?”

“当然,我们一起携手,让技术不再成为阻隔,而是让我们相聚在更广阔的创新天地中。”

两人决定在繁忙的生活中晚上花时间一起努力学习。江傲云耐心地向苏云枫说着C#的优点和知识,而苏云枫也展现出非凡的领悟力,任着深厚的java功底,很快就掌握了在.net平台下开发程序的要领。待个把月后,江傲云给苏云枫说:“我这有50道初中级C#面试题,你也可以叫.net面试题,先背会这50道吧,对你转行到C#开发有好处。”

初中级C#面试题

当准备C#编程语言的初级到中级面试时,以下是一些常见的面试问题,准备面试时,理解并熟练掌握这些问题对于准备初级到中级的C#开发人员来说至关重要。同时,在回答问题时,可以通过简洁的例子或者实际经验来进一步说明你的理解。

1. C#中堆和栈的区别?

栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。堆:一般由程序员分配释放。用 new、malloc 等分配内存函数分配得到的就是在堆上。存放在栈中时要管存储顺序,保持着先进后出的原则,他是一片连续的内存域,有系统自动分配和维护;

堆:是无序的,他是一片不连续的内存域,有用户自己来控制和释放,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC)来回收。栈内存无需我们管理,也不受 GC 管理。当栈顶元素使用完毕,立马释放。而堆则需要 GC 清理。使用引用类型的时候,一般是对指针进行的操作而非引用类型对象本身。但是值类型则操作其本身。

2. C#中的委托是什么?事件是不是一种委托?

在 C# 中,委托(Delegate)是一种类型,它可以存储对方法的引用,并允许您像其他数据类型一样对方法进行传递。委托允许您将方法作为参数传递给其他方法,或者从方法中返回一个方法。它们提供了一种方法来实现委托和事件处理,支持回调功能。

委托本质上是一种类型安全的函数指针,它可以指向一个或多个方法。委托的实例化后,可以像函数一样被调用。它们用于实现事件和回调功能,允许程序设计采用松耦合的方式,增强了代码的灵活性和可扩展性。

事件(Event)则是基于委托的概念,用于实现发布者/订阅者模式(Publisher/Subscriber pattern)。在 C# 中,事件是一种特殊的委托,它允许对象通知其他对象发生了特定的动作或状态改变。事件提供了更安全、更规范化的方式,用于订阅和处理特定操作的通知。

虽然事件和委托都涉及委托类型,但事件是委托的一种特殊形式,它可以用于提供更加安全和封装的事件通知机制。事件可以被其他类订阅,但它本身不是委托。

总结:

事件在 C# 中通常通过委托来实现,但委托并不一定是事件。事件提供了对委托的封装,通过事件的机制,它能够提供更加安全、规范化的订阅和通知模式。

3. C#静态构造函数特点是什么?

在 C# 中,静态构造函数(static constructor)是用来初始化静态成员或者执行一次性初始化操作的特殊构造函数。以下是静态构造函数的特点:

  1. 自动触发: 静态构造函数不需要显式调用,它会在类被加载时自动触发,而且只会执行一次。它在首次访问类的任何静态成员之前调用。
  2. 没有访问修饰符和参数: 静态构造函数没有访问修饰符(如 public、private),也不允许传递参数。它仅允许在同一个类中声明一个静态构造函数。
  3. 无法被直接调用: 与实例构造函数不同,静态构造函数无法被显式调用,它是由运行时在必要时自动调用的。
  4. 执行顺序: 静态构造函数的执行是在类第一次实例化、静态成员被访问或者在程序中第一次访问静态成员之前执行。
  5. 线程安全: 静态构造函数是线程安全的,当类被加载时,系统确保只有一个线程执行静态构造函数。
  6. 用途: 通常,静态构造函数用于初始化静态成员变量或执行一次性的初始化操作。这些操作可能包括初始化静态数据,建立连接或加载资源等。

静态构造函数对于确保静态成员的初始化是至关重要的,它们提供了一种可靠的方式,确保静态成员在被访问之前被正确初始化。

4. CTS、CLS、CLR 分别作何解释

5. C#中什么是值类型与引用类型?

值类型:struct、enum、int、float、char、bool、decimal
引用类型:class、delegate、interface、array、object、string

6. 请详述在 C#中类(class)与结构(struct)的异同?

在 C# 中,类(class)和结构(struct)是两种用于定义自定义数据类型的关键概念。它们有一些相似之处,也有一些重要的区别点。

相似之处:

  1. 成员变量: 类和结构都可以包含字段(fields)、属性(properties)、方法(methods)和其他成员变量。
  2. 构造函数: 两者都可以拥有构造函数,用于初始化实例。
  3. 继承性: 类和结构都支持接口的实现,但只有类支持继承。

区别:

  1. 内存分配:
  1. 继承和多态:
  1. 装箱和拆箱:
  1. 默认访问修饰符:
  1. 适用场景:

总结:

背会50道初中级C#面试题.net面试题卷死java

7. new 关键字的作用

在 C# 中,new 关键字有几种不同的用途,具体取决于它在代码中的上下文:

  1. 实例化对象:
  1. 方法重写(方法屏蔽):
  1. 字段隐藏:
  1. 泛型约束:

总的来说,new 关键字主要用于创建对象实例、方法的屏蔽(不推荐)、字段的隐藏(也不推荐)以及泛型约束中对构造函数的要求。其最常见的使用是用于实例化对象,创建类的实例。

8. int?和 int 有什么区别

int?为可空类型,默认值可以是 null
int 默认值是 0
int?是通过 int 装箱为引用类型实现

9. C#中值传递与引用传递的区别是什么?

值传递时,系统首先为被调用方法的形参分配内存空间,并将实参的值按位置一一对应地复制给形参,此后,被调用方法中形参值得任何改变都不会影响到相应的实参;引用传递时,系统不是将实参本身的值复制后传递给形参,而是将其引用值(即地址值)传递给形参。

因此,形参所引用的该地址上的变量与传递的实参相同,方法体内相应形参值得任何改变都将影响到作为引用传递的实参。简而言之,按值传递不是值参数是值类型,而是指形参变量会复制实参变量,也就是会在栈上多创建一个相同的变量。而按引用传递则不会。可以通过 ref 和 out 来决定参数是否按照引用传递。

10. C#中参数传递 ref 与 out 的区别?

(1)ref 指定的参数在函数调用时必须先初始化,而 out 不用。

(2)out 指定的参数在进入函数时会清空自己,因此必须在函数内部进行初始化赋值操作,而 ref 不用

总结:ref 可以把值传到方法里,也可以把值传到方法外;out 只可以把值传到方法外

注意:string 作为特殊的引用类型,其操作是与值类型看齐的,若要将方法内对形参赋值后的结果传递出来,需要加上 ref 或 out 关键字。

11. C#中什么是装箱和拆箱?

装箱:对值类型在堆中分配一个对象实例,并将该值复制到新的对象中。

拆箱:检查对象实例,确保它是给定值类型的一个装箱值。将该值从实例复制到值类型变量中。在装箱时是不需要显式的类型转换的,不过拆箱需要显式的类型转换。

int i=0;
System.Object obj=i; //这个过程就是装箱!就是将 i 装箱!
int j=(int)obj;//这个过程 obj 拆箱!

12.C#实现多态的过程中 overload 重载 与 override 重写的区别?

在 C# 中,多态是面向对象编程中的重要概念,而 overload(重载)和 override(重写)是实现多态性的两种方式。

重载(Overload):

  public class Calculator
  {
      public int Add(int a, int b)
      {
          return a + b;
      }

      public float Add(float a, float b)
      {
          return a + b;
      }
  }

重写(Override):

  public class Shape
  {
      public virtual void Draw()
      {
          Console.WriteLine("Drawing a shape -- from jhrs.com");
      }
  }

  public class Circle : Shape
  {
      public override void Draw()
      {
          Console.WriteLine("Drawing a circle  --from jhrs.com");
      }
  }

初中级C#面试题.net面试题卷死java

区别总结:

  1. 作用对象不同: 重载是针对同一个类中的方法,通过不同的参数列表进行区分;重写是针对基类中的虚拟方法,让派生类中的方法覆盖基类的行为。
  2. 关键字不同: 重载使用相同的方法名但不同的参数列表;重写使用 override 关键字。
  3. 使用场景不同: 重载用于提供类似但具有不同参数的方法,而重写用于实现继承类中的多态性,允许子类提供自己的实现。

重载和重写都是多态的表现形式,但针对不同的场景,提供了不同的实现方式。

.net面试题卷死java

13. C# 中 static 关键字的作用?

对类有意义的字段和方法使用 static 关键字修饰,称为静态成员,通过类 名 加 访 问 操 作 符 “ .” 进 行 访 问 ; 对 类 的 实 例 有 意 义 的 字 段 和 方 法 不 加static 关键字,称为非静态成员或实例成员。

  1. 静态字段(Static Fields)和属性(Static Properties)
  2. 静态方法(Static Methods)
  3. 静态类(Static Classes)
  4. 静态构造函数(Static Constructor)

注: 静态字段在内存中只有一个拷贝,非静态字段则是在每个实例对象中拥有一个拷贝。而方法无论是否为静态,在内存中只会有一份拷贝,区别只是通过类名来访问还是通过实例名来访问。

14. C# 成员变量和成员函数前加 static 的作用?

在 C# 中,当在类中声明成员变量(字段)和成员函数(方法)时使用 static 关键字,其作用取决于该关键字应用的位置和上下文。

针对成员变量(字段):

  1. 静态字段(Static Fields):

示例:

public class MyClass
{
    public static int staticField; // 静态字段,属于类而不是实例
}

针对成员函数(方法):

  1. 静态方法(Static Methods):

示例:

public class MyClass
{
    public static void StaticMethod() // 静态方法,不需要实例化类即可调用
    {
        // Some logic here
    }
}

总结作用:

15. C#中索引器的实现过程,是否只能根据数字进行索引?

在 C# 中,索引器(Indexer)是一种特殊的属性,允许类或结构像数组一样使用索引来访问其元素。索引器并不限于使用数字来进行索引,它可以自定义索引方式,例如使用整数、字符串、对象等作为索引。

索引器的实现过程:

  1. 定义索引器: 索引器在类中被定义为类的属性,它允许类对象像数组一样被索引访问。
public class ShueyeClass
{
    private string[] data = new string[10];

    public string this[int index] // 索引器的定义
    {
        get
        {
            return data[index];
        }
        set
        {
            data[index] = value;
        }
    }
}

初中级C#面试题.net面试题卷死java

  1. 索引器语法: 索引器的语法类似于属性,使用 this[] 来定义,并包含 getset 访问器,可以根据传入的索引进行操作。
  2. 不仅限于数字索引: 索引器并不限制索引类型。开发者可以根据需求定义任何类型的索引,如整数、字符串、对象等。
    public class ShueyeClass
    {
        private Dictionary<string, string> data = new Dictionary<string, string>();

        public string this[string key] // 使用字符串索引
        {
            get
            {
                return data[key];
            }
            set
            {
                data[key] = value;
            }
        }
    }

初中级C#面试题.net面试题卷死java

总结:

索引器在 C# 中允许类对象通过自定义索引方式(并非仅限于数字)进行访问,开发者可以根据需要定义自己的索引类型,使类更加灵活并允许按照不同的索引方式访问其元素。索引器的本质是为类提供类似数组的索引方式,但并不局限于整数类型。

16. C#中 abstract class 和 interface 有什么区别?

在 C# 中,抽象类(abstract class)和接口(interface)都是用于实现面向对象编程中的多态性和封装性的概念,但它们有一些重要区别:

抽象类(Abstract Class):

  1. 定义: 抽象类是一个类,可以包含抽象成员(即方法、属性或索引器),并且可以包含具体的实现。
  2. 特点: 抽象类可以包含成员字段、普通方法(有具体实现)、抽象方法(无实现,只有签名),以及属性等。
  3. 实现: 抽象类本身不能被实例化,必须被继承,并且继承的子类(派生类)必须实现(覆盖)所有的抽象成员,除非该派生类也是抽象类。
  4. 单继承: 一个类只能继承一个抽象类,因为 C# 不支持多重继承。

接口(Interface):

  1. 定义: 接口是一种抽象类型,仅包含成员的签名,没有实现。它是对行为的抽象描述。
  2. 特点: 接口只能包含成员的声明(方法、属性、事件等),不包含成员的实现。实现接口的类必须提供接口中声明的所有成员的实现。
  3. 多继承: 类可以实现多个接口,即一个类可以同时实现多个接口。
  4. 用途: 接口用于定义约定,确保类具有特定的行为,允许不同类之间实现相同的行为。

区别总结:

  1. 实现差异: 抽象类可以包含成员的具体实现,而接口只包含成员的声明而没有实现。
  2. 多重继承: 类可以实现多个接口,但只能继承一个抽象类。
  3. 设计理念: 抽象类表示 is-a 关系,接口表示 has-a 关系。
  4. 关注点不同: 抽象类关注类之间的相似性,接口关注类的行为。

选择使用时的建议:

17. C#中用 sealed 修饰的类有什么特点?

在 C# 中,使用 sealed 关键字修饰的类具有以下特点:

  1. 不可被继承: 当一个类被标记为 sealed(密封类),该类就不能被其他类继承。
  2. 终结类的层次结构: sealed 关键字用于终结类的层次结构,即它阻止其他类从这个类派生,从而不允许对该类的进一步扩展或修改。
  3. 最终性: 在继承层次结构中,sealed 类是最终的,它不能成为其他类的基类。
  4. 性能优化: 使用 sealed 关键字可以使得编译器进行更好的优化,因为它知道该类不会被继承,可以进行更多的静态绑定和内联优化。

示例:

public sealed class ShueyeClass
{
    // Class members and methods
}

总体来说,sealed 关键字用于禁止其他类继承被标记为 sealed 的类。这种设计决策通常是因为某些类不适合被继承,或者是出于性能、安全性或设计考虑而限制对类的进一步扩展。

18. 下面代码中字符串的区别

string str=null 和 string str=”” 和 stringstr=string.Empty

在 C# 中,这三种赋值方式 string str = null, string str = "", 和 string str = string.Empty 有以下区别:

  1. string str = null:
  1. string str = “”:
  1. string str = string.Empty:

综上所述:

19. 这些变量有些错误是错在哪里?

byte b = ‘a’; byte c = 1; byte d = ‘ab’; byte e = ‘啊’; byte g =256;

在这段代码中,有几个地方存在错误:

  1. byte b = ‘a’;
  1. byte c = 1;
  1. byte d = ‘ab’;
  1. byte e = ‘啊’;
  1. byte g = 256;

修正方法:

20. string 和 StringBuilder 的区别

在 C# 中,stringStringBuilder 是用于处理字符串的两种主要类型,它们有以下区别:

string 类型:

  1. 不可变性:
  1. 性能影响:
  1. 线程安全:
  1. 使用简单:

StringBuilder 类型:

  1. 可变性:
  1. 性能优化:
  1. 线程不安全:
  1. 适用场景:

总结:

初中级C#面试题.net面试题卷死java

21. 什么是扩展方法?

一句话解释,扩展方法使你能够向现有类型“添加”方法,无需修改类型条件:按扩展方法必须满足的条件,

  1. 必须要静态类中的静态方法
  2. 第一个参数的类型是要扩展的类型,并且需要添加 this 关键字以标识其为扩展方法建议:

通常,只在不得已的情况下才实现扩展方法,并谨慎的实现使用:不能通过类名调用,直接使用类型来调用。

22. 特性是什么?如何使用?

特 性 与 属 性 是 完 全 不 相 同 的 两 个 概 念 , 只 是 在 名 称 上 比 较 相 近 。Attribute 特性就是关联了一个目标对象的一段配置信息,本质上是一个类,其为目标元素提供关联附加信息,这段附加信息存储在 dll 内的元数据,它本身没什么意义。运行期以反射的方式来获取附加信息。

23.什么叫应用程序域(AppDomain)

一种边界,它由公共语言运行库围绕同一应用程序范围内创建的对象建立(即,从应用程序入口点开始,沿着对象激活的序列的任何位置)。应用程序域有助于将在一个应用程序中创建的对象与在其他应用程序中创建的对象隔离,以使运行时行为可以预知。在一个单独的进程中可以存在多个应用程序域。应用程序域可以理解为一种轻量级进程。起到安全的作用。占用资源小。

24. byte a =255;a+=5;a 的值是多少?

byte 的取值范围是-2 的 8 次方至 2 的 8 次方-1,-256 至 255,a+=1
时,a 的值时 0,a+=5 时,a 的值是 0,所以 a+=5 时,值是 4

25. const 和 readonly 有什么区别?

都可以标识一个常量。主要有以下区别:

  1. 初始化位置不同。const 必须在声明的同时赋值;readonly 即可以在声明处赋值。
  2. 修饰对象不同。const 即可以修饰类的字段,也可以修饰局部变量。readonly 只能修饰类的字段
  3. const 是编译时常量,在编译时确定该值;readonly 是运行时常量,在运行时确定该值。
  4. const 默认是静态的;而 readonly 如果设置成静态需要显示声明
  5. 修饰引用类型时不同,const 只能修饰 string 或值为 null 的其他引用类型;readonly 可以是任何类型。

26.分析下面代码,a、b 的值是多少?

分析:一个字母、数字占一个 byte,一个中文占占两个 byte,所以 a=8,b=5

27. String s = new String( “ xyz ” ); 创 建 了 几 个 String Object?

两个对象,一个是“xyz”,一个是指向“xyz”的引用对象 s。

28. c#可否对内存直接操作

C#在 unsafe 模式下可以使用指针对内存进行操作, 但在托管模式下不可以使用指针,C#NET 默认不运行带指针的,需要设置下,选择项目右键->属性->选择生成->“允许不安全代码”打勾->保存

29. 什 么 是 强 类 型 , 什 么 是 弱 类 型 ? 哪 种 更 好 些 ? 为 什
么?

强类型是在编译的时候就确定类型的数据,在执行时类型不能更改,而弱类型在执行的时候才会确定类型。没有好不好,二者各有好处,强类型安全,因为它事先已经确定好了,而且效率高。

一般用于编译型编程语言,如 c++,java,c#,pascal 等,弱类型相比而言不安全,在运行的时候容易出现错误,但它灵活,多用于解释型编程语言,如 javascript等。

30. Math函数应用

Math.Round(11.5) 等 于 多 少 ?

Math.Round(-11.5) 等 于 多少?

Math.Round(-11.3)呢?

31. &和&&的区别相同点

在 C# 中,&&& 都是逻辑运算符,它们有以下区别和相同点:

区别:

  1. 逻辑运算符的类型:
  1. 短路求值:

相同点:

  1. 作用:
  1. 返回值:

例子:

int a = 5, b = 3;
bool resultBitwise = (a & b) > 0; // 按位与运算
bool resultLogical = (a > 0) && (b > 0); // 逻辑与运算

// 对于位运算
Console.WriteLine(resultBitwise); // 输出结果是 true 或 false

// 对于逻辑运算
Console.WriteLine(resultLogical); // 输出结果是 true 或 false

初中级C#面试题.net面试题卷死java

总体来说,& 是按位与运算符,适用于位操作,而 && 是逻辑与运算符,适用于逻辑运算,具有短路求值的特性。

32. i++和++i 有什么区别?

  1. i++是先赋值,然后再自增;++i 是先自增,后赋值。
  2. i=0,i++=0,++i=1;Console.WriteLine(++i==i++); 结果为 true

33. as 和 is 的区别

as 在转换的同时判断兼容性,如果无法进行转换,返回位 null(没有产生新的对象),as 转换是否成功判断的依据是是否位 null is 只是做类型兼容性判断,并不执行真正的类型转换,返回 true 或 false,对象为 null也会返回 false。as 比 is 效率更高,as 只需要做一次类型兼容检查。

34. 谈谈 final、finally 的区别。

final : 不 能 作 为 父 类 被 继 承 。 一 个 类 不 能 声 明 是 final , 又 声 明 为abstract。

finally:用于 try{}catch{}finally{}结构,用于异常处理时执行任何清除操作。

35. 简述 C#成员修饰符

在 C# 中,成员修饰符是用于修饰类的成员(字段、方法、属性、事件等)的关键字,它们控制成员的行为、可见性、继承性等。以下是一些常用的成员修饰符:

  1. public:
  1. private:
  1. protected:
  1. internal:
  1. protected internal:
  1. static:
  1. readonly:
  1. abstract:
  1. virtual:
  1. override:

这些修饰符可以单独使用或者组合使用,用于控制成员的访问、行为和继承性。通过使用这些修饰符,可以定义出适当可见性和行为的类成员,以满足代码设计和安全性需求。

36. 什么是匿名类,有什么好处?

匿名类(Anonymous Types)是 C# 中的一种特殊类型,它允许开发者在编写代码时,临时创建一个只读类型,并在使用时对其进行初始化。匿名类可以使用 var 关键字声明,不需要显式指定类型名称,其结构由编译器自动推断生成。

特点与好处:

  1. 简化代码: 匿名类允许开发者在不定义新类型的情况下,快速地创建一个临时的只读类型。这样可以减少不必要的类型定义,简化代码。
  2. 方便初始化: 可以轻松地在代码中进行临时数据初始化,这对于一些临时性的数据结构、LINQ 查询结果等非常有用。
  3. 自动推断类型: 编译器会根据初始化时的赋值自动推断成员的类型。因此,使用匿名类不需要开发者手动定义属性的数据类型。
  4. 只读性质: 匿名类的属性都是只读的,一旦初始化就不能再修改其值。这有助于确保数据的不变性。

举例:

var person = new { Name = "John", Age = 30 }; // 声明一个匿名类

Console.WriteLine($"Name: {person.Name}, Age: {person.Age}"); // 访问匿名类属性

var employee = new { Name = "Alice", Department = "IT" }; // 另一个匿名类

Console.WriteLine($"Name: {employee.Name}, Department: {employee.Department}");

初中级C#面试题.net面试题卷死java

匿名类通常用于临时性的数据结构,或者在 LINQ 查询等场景中,用于生成临时投影。尽管匿名类在某些场景下非常便利,但由于其只能用于局部范围,因此不能用作公共 API 的返回类型。

37. 说说什么是逐字字符串

在 C# 中,逐字字符串(verbatim string)是一种特殊的字符串表示形式,它允许包含转义字符的原始文本而不进行转义处理。通常,在字符串中,使用反斜杠(\)作为转义字符,用来表示特殊字符或序列,如换行符(\n)、制表符(\t)、或双引号(\”)等。

逐字字符串通过在字符串的开头添加符号 @ 来定义。使用逐字字符串,可以轻松地包含多行文本或文件路径,而无需在字符串中使用双重转义。例如:

string path = @"C:\Users\Username\Documents\File.txt";
string multilineText = @"This is a 
multi-line
text.";

在逐字字符串中,反斜杠不再表示转义字符,而会被视为普通字符。这对于路径、正则表达式、XML 或任何需要大量反斜杠的文本非常有用,因为它消除了双重转义所带来的混淆和错误。

38. 列举你知道的数字格式化转换

在 C# 中,有多种数字格式化转换方式,其中一些常见的包括:

  1. 标准数值格式:C# 提供了一系列标准数值格式,例如:
  1. 自定义数值格式:可以使用自定义格式字符串进行数值格式化,例如:

这些格式可以通过 ToString 方法与数值类型一起使用,例如:

int number = 123456;
Console.WriteLine(number.ToString("N")); // 输出:123,456.00

double value = 123.456789;
Console.WriteLine(value.ToString("0.00")); // 输出:123.46

这些格式化方法可根据需要对数字进行不同类型的显示,如货币值、百分比、科学记数法等。格式化提供了更灵活的方式来显示数值,使其更易读或适合特定的需求。

39. 说说字符串拼接、字符串内插法

在 C# 中,有多种方法可以组合字符串。两种主要的方式是字符串拼接和字符串内插法。

字符串拼接(String Concatenation):

字符串拼接是指将多个字符串连接在一起形成一个新的字符串。在 C# 中,最常见的字符串拼接方法是使用 + 运算符或 String.Concat 方法。例如:

使用 + 运算符:

string firstName = "Jhrs";
string lastName = ".com";

string fullName = firstName + " " + lastName;

初中级C#面试题.net面试题卷死java

使用 String.Concat 方法:

string message = String.Concat("znlive, ", ".com!");

字符串内插法(String Interpolation):

字符串内插法是 C# 6.0 引入的一种更直观和简洁的字符串组合方法。它使用 $ 符号和大括号 {} 来在字符串中嵌入表达式或变量。例如:

string name = "jhrs.com";
int age = 30;

string description = $"My name is {name} and I am {age} years old.";

这种方式更清晰,因为在大括号内可以直接嵌入变量或表达式,而无需使用额外的运算符或方法。它使得代码更易读和维护,并提供了更直接的字符串构建方式。

字符串内插法使得代码更具可读性,特别是当需要插入多个变量或表达式时,它比传统的字符串拼接更为简洁,易于理解。

40. 什么是虚函数?什么是抽象函数?

在 C# 中,虚函数和抽象函数与 C++ 中的概念有些类似,但有一些细微的差异。

虚函数(Virtual Function):在 C# 中,使用 virtual 关键字标记的函数被称为虚函数。虚函数允许在派生类中重写(override)基类中的实现。这意味着在基类中使用 virtual 关键字声明的函数可以在派生类中被覆盖或重写,允许对象在运行时调用正确版本的函数,以实现多态性。在派生类中使用 override 关键字来重写基类中的虚函数。

抽象函数(Abstract Function):在 C# 中,可以创建抽象类和抽象函数。抽象函数是一种在抽象类中声明但没有具体实现的函数。使用 abstract 关键字声明的函数称为抽象函数,它只有方法签名而没有实际的方法体。抽象类本身也可以包含非抽象方法,但只要类中有一个抽象函数,那么这个类就必须被声明为抽象类。派生类必须实现抽象类中的所有抽象函数,除非这个派生类本身也被声明为抽象类。

// 虚函数示例
public class BaseClass
{
    public virtual void Display()
    {
        Console.WriteLine("jhrs.com友情提示:狗日的,这是基类的显示方法哈,不准抄袭!");
    }
}

public class DerivedClass : BaseClass
{
    public override void Display()
    {
        Console.WriteLine("znlive.com友情提示:娘希匹,大爷我重写了jhrs.com友情提示。。");
    }
}

// 抽象函数示例
public abstract class AbstractClass
{
    public abstract void AbstractMethod();
}

public class ConcreteClass : AbstractClass
{
    public override void AbstractMethod()
    {
        Console.WriteLine("guowaivps.org 友情提示:哈哈,你个鬼儿子完蛋了吧,我这儿实现了AbstractClass抽象类的方法哦。");
    }
}

初中级C#面试题.net面试题卷死java

总的来说,C# 中的虚函数允许在派生类中重写基类中的方法,而抽象函数用于定义抽象类的接口,要求派生类实现特定方法。

41. Webservice 与 Webapi 的区别?

Webservice它是基于 SOAP 协议的,数据格式是 XML (SOAP )只支持 HTTP 协议,不是开源的,但可以被任意一个了解 XML 的人使用它只能部署在 IIS 上,Webapi Web API 是一个开源的、理想的、构建REST-ful 服务的技术它也支持 MVC 的特征,像路由、控制器、action、filter 等,它可以部署在应用程序和 IIS 上Response 可以 被 Web API 的 MediaTypeFormatter 转换 成 Json、XML 或者任何你想转换的格式。

42. ADO.NET 常用对象有哪些?

42.1 Connection对象

Connection主要是开启程序和数据库之间的连接。没有利用连接对象将数据库打开,是无法从数据库中取得数据的。Close 和 Dispose 的区别,Close 以后还可以 Open,Dispose 以后则不能再用。

42.2 Command对象

Command主要可以用来对数据库发出一些指令,例如可以对数据库下达查询、新增、修改、删除数
据等指令,以及调用存在数据库中的存储过程等。这个对象是架构在 Connection对象上,也就是 Command 对象是通过在 Connection 对象连接到数据源。

42.3 DataAdapter对象

DataAdapter主要是在数据源以及 DataSet 之间执行数据传输的工作,它可以透过 Command 对象下达命令后,并将取得的数据放入 DataSet 对象中。这个对象是架构在 Command 对象上,并提供了许多配合 DataSet 使用的功能。

42.4 DataSet对象

DataSet这个对象可以视为一个暂存区(Cache),可以把从数据库中所查询到的数据保留起来,甚至可以将整个数据库显示出来,DataSet 是放在内存中的。

42.5 DataReader对象

DataReader对象只是一次一次向下循序的读取数据源中的数据,这些数据是存在数据库服务器中的,而不是一次性加载到程序的内存中的,只能(通过游标)读 取 当 前 行 的 数 据 , 而 且 这 些 数 据 是 只 读 的 , 并 不 允 许 作 其 它 的 操 作 。

因 为DataReader 在读取数据的时候限制了每次只读取一条,而且只能只读,所以使用起来不但节省资源而且效率很好。

43. 什么是托管和非托管?

托管代码:是由公共语言运行库(CLR)执行的代码,而不是由操作系统直接执行。

有关内存管理(内存申请,内存释放,垃圾回收之类的)全部都是.net 的 CLR来管理。非托管代码:直接编译成目标计机码,由操作系统直接执行的代码,内存回收要继承 IDisposable 接口手动回收。

44. 为什么说在.NET 托管代码中不必担心内存泄漏?

在 .NET 等托管代码的环境中,内存泄漏问题相对较少或更容易管理的原因有几点:

自动内存管理(Garbage Collection)

  1. 垃圾回收器(Garbage Collector):在托管环境中,有一个垃圾回收器负责管理内存。这个回收器周期性地扫描和识别不再被程序使用的对象,并释放它们所占用的内存空间。这大大减少了程序员需要手动管理内存的负担,避免了许多常见的内存泄漏问题。
  2. 自动内存分配和释放:在托管环境中,内存的分配和释放都是自动进行的。当对象不再被引用时,垃圾回收器负责及时将其标记为可回收,从而释放内存,避免了程序员忘记释放内存的情况。

强类型语言和较为严格的规范

  1. 强类型检查:语言本身的类型安全性和编译器检查有助于减少许多常见的内存错误,比如访问未分配的内存或释放后再次访问的情况。
  2. 异常处理和对象生命周期管理:在托管环境中,异常处理以及对象的生命周期管理得到更好的支持,有助于避免许多可能导致内存泄漏的错误。

尽管托管环境有上述优势,但仍然存在一些情况可能导致“泄漏”或者资源未正确释放,例如:

尽管垃圾回收器能够管理大部分的内存分配和回收,但仍需开发人员注意不要持有不必要的资源或者避免长时间持有对其他对象的引用,以免影响内存的正常回收。

45. 什么是 MVC 模式

MVC(Model-View-Controller)是一种软件设计模式,旨在帮助开发者更好地组织和管理用户界面和应用程序的逻辑。它将应用程序分为三个主要组成部分:

  1. Model(模型):模型是应用程序中包含数据和业务逻辑的部分。它代表应用程序中的数据结构、状态和行为。模型不依赖于用户界面,而是负责处理数据的存储、检索、操作和验证。任何关于数据的更改都应该首先在模型中进行,确保数据的一致性和有效性。
  2. View(视图):视图是用户界面的呈现部分。它负责展示数据给用户,并接收用户的输入。视图能够展示来自模型的数据,并向用户显示信息。视图通常是用户与应用程序交互的地方,如页面、窗口、按钮等。
  3. Controller(控制器):控制器是连接模型和视图的部分。它接受来自用户界面的输入,调用相关的模型处理数据逻辑,并决定如何更新视图。控制器接收用户的请求,更新数据模型,然后选择合适的视图来显示结果。它起着协调者的作用,将用户的动作与应用程序的其他部分联系起来。

MVC 模式的优势包括:

许多现代的Web框架和应用程序框架都采用了MVC模式,以便更好地组织代码、降低耦合度,并提供更好的用户体验。

46. 能用 foreach 遍历访问的对象的要求

在 C# 中,foreach 循环可以用于遍历访问实现了 IEnumerableIEnumerable<T> 接口的对象。这些接口定义了遍历集合元素的方法。

要使用 foreach 循环遍历对象,对象必须满足以下要求:

  1. 实现 IEnumerable 接口:对象必须实现 IEnumerable 接口或者 IEnumerable<T> 接口之一。这些接口定义了迭代集合元素的方法。
  2. 包含 GetEnumerator 方法IEnumerable 接口包含一个名为 GetEnumerator 的方法,它返回一个实现 IEnumerator 接口的对象。IEnumerator 接口用于在集合上进行迭代。
  3. 实现 MoveNext 和 Current 方法IEnumerator 接口包含 MoveNext()Current 属性。MoveNext() 方法用于移动到集合中的下一个元素,Current 属性用于获取当前迭代器指向的元素。

示例:

// 示例类实现 IEnumerable 接口
public class MyCollection : IEnumerable
{
    private int[] data = { 1, 2, 3, 4, 5 };

    public IEnumerator GetEnumerator()
    {
        return data.GetEnumerator();
    }
}

// 使用 foreach 遍历 MyCollection 对象
MyCollection collection = new MyCollection();
foreach (var item in collection)
{
    Console.WriteLine(item);
}

初中级C#面试题.net面试题卷死java

foreach 循环对实现了 IEnumerableIEnumerable<T> 接口的对象进行迭代,简化了遍历集合的过程。常见的集合类,如数组、List、Dictionary 等,已经实现了这些接口,因此可以直接用 foreach 循环进行遍历。

47. 什么是反射?

在 C# 中,反射(Reflection)是一种强大的机制,允许程序在运行时获取关于程序集(assembly)、类型(Type)、成员(Member)、方法和属性等信息的能力。通过反射,开发者可以动态地获取和使用类型的信息,而无需在编译时就了解这些信息。

反射允许在程序运行时:

  1. 检查类型的信息:包括类的结构、成员、方法、属性等。
  2. 实例化对象:动态地创建实例化对象。
  3. 调用方法和属性:对对象的方法、属性进行调用。
  4. 操作程序集:加载、检查和处理程序集。

一些常见的反射类和概念:

示例代码如下:

using System;
using System.Reflection;

public class MyClass
{
    public void MyMethod()
    {
        Console.WriteLine("jhrs.com - 调用了MyMethod方法。");
    }
}

class Program
{
    static void Main()
    {
        Type type = typeof(MyClass); // 获取 MyClass 的 Type 信息

        // 获取方法信息
        MethodInfo methodInfo = type.GetMethod("MyMethod");

        // 创建对象实例
        object obj = Activator.CreateInstance(type);

        // 调用方法
        methodInfo.Invoke(obj, null); // 调用 MyMethod 方法
    }
}

初中级C#面试题.net面试题卷死java

这段代码演示了如何使用反射来获取类型信息,获取方法信息,并动态地调用该方法。反射在很多框架和库中被广泛应用,用于实现动态加载程序集、插件系统、序列化和反序列化等功能。尽管反射功能强大,但在运行时使用它会增加一些性能开销,并且使得代码复杂性增加,因此应谨慎使用。

48. ORM中的延迟加载与直接加载有什么异同?

在对象关系映射(ORM)中,延迟加载(Lazy Loading)和直接加载(Eager Loading)是两种数据加载策略,用于在获取对象关联数据时进行不同的操作。

1. 延迟加载(Lazy Loading):

2. 直接加载(Eager Loading):

3. 异同点总结:

  1. 时机:延迟加载是在需要时才加载数据,而直接加载是在初始加载数据时就获取所有相关数据。
  2. 性能:延迟加载可以节省资源,但频繁访问关联数据时可能导致性能问题。直接加载可以提高性能,但可能导致一次性加载大量数据。
  3. 适用性:根据应用程序的具体需求,对于不同的场景和对象之间的关系,选择合适的加载策略是很重要的。

在实际开发中,根据数据访问的模式、数据量和性能需求,开发人员会选择合适的加载策略来平衡性能和资源的使用。有些ORM框架允许开发者根据需要来配置延迟加载或直接加载。

49. 简述 Func 与 Action 的区别?

在 C# 中,FuncAction 都是委托(Delegate)的泛型版本,用于定义函数指针。它们之间的区别主要在于它们代表的方法签名和返回值。

Action:

Action 是一个委托类型,它代表一个无返回值的方法(即 void 方法)。它可以用于表示没有参数或多个参数的方法,但方法本身不返回任何结果。

// 代表无参数无返回值的方法
Action action1 = () => { /* do something */ };

// 代表带有一个参数的无返回值方法
Action<int> action2 = (x) => { /* do something with x */ };

Func:

Func 也是一个委托类型,但不同于 Action,它代表带有返回值的方法。它的最后一个泛型参数表示方法的返回类型,之前的参数表示方法的参数类型。

// 代表有一个整数参数并返回字符串的方法
Func<int, string> func1 = (x) => { /* jhrs.com提示:参数为int类型,返回一个字符串. */ };

// 代表有两个参数(整数和字符串),返回布尔值的方法
Func<int, string, bool> func2 = (x, y) => { /* jhrs.com提示:参数2个,分别是int,string类型,返回bool结果 */ };

区别总结:

通过使用 ActionFunc,可以更灵活地处理不同参数和返回类型的方法,从而简化委托的使用和定义。常用于异步编程、LINQ 查询和事件处理等场景。

50. 23 种设计模式分别叫什么名称,如何分类?

经典的设计模式分分三类:创建模式,行为模式,结构模式。

使用C#写的完整设计模式示例代码见这里:https://jhrs.com/2023/47094.html/3

50.1 创建模式包含

1).单例模式,2).工厂模式 3).建造者模式 4).原型模式 5).工厂方法模式

50.2 行为模式包含

1).策略模式
2).模板方法模式
3).观察者模式
4).迭代子模式
5).责任链模式
6).命令模式
7).备忘录模式公众号:DotNet开发跳槽
8).状态模式
9).访问者模式
10).中介者模式
11).解释器模式

50.3 结构设计模式包含

1).适配器模式
2).装饰器模式
3).代理模式
4).外观模式
5).桥接模式
6).组合模式
7).享元模式

退出移动版