C# dotnet的基础面试题
Yuxuan Wu Lv13

最近,整理了一份 c#、.net 基础面试题,其中多少引用了前辈们写的,也加了自己的理解。不对的地方,还请大家多多指正,共同进步,非常感谢!

如有侵权请私信我。https://zhuanlan.zhihu.com/p/355257871


题目概要

1、ASP.NET页面之间传值方式?

2、如何理解装箱和拆箱?

3、C#中什么是值类型与引用类型?

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

5、virtual 和 abstract

6、简述 private、 protected、 public、 internal 修饰符的访问权限。

7、C#中堆和栈的区别? 值类型 栈 引用类型 堆

8、在ASP.NET中所有的自定义用户控件都必须继承自?

10、GC(Garbage Collection)

11、CLR(Common Language Runtime)

12、静态构造函数

13、文件I/O

14、序列化与反序列化

15、线程同步

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

17、using关键字的使用场景

18、new关键字的使用场景

19、委托与事件

20、重载(overload)与重写(override)的区别

21、return执行顺序

22、switch(expression)

23、反射Reflection

24、property与attribute的区别

25、(Class)和实例(Instance)

26、类和类的实例有什么区别?

27、C# 中static关键字的作用?

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

29、文件编码格式

30、值传递与引用传递解释?

31、参数传递 ref 与 out 的区别

32、什么是内存泄漏?

33、跨域

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

35、简述Func与Action的区别?

36、能用foreach遍历访问的对象的要求?

37、什么是泛型?

38、Final

39、数据库操作的相关类

40、http://ADO.NET 五大对象

41、C# DataTable和DataSet 区别?

42、索引器(Indexers)

43、POST和GET深入理解

44、C#中用sealed修饰的类有什么特点?

45、string和StringBuilder的区别,两者性能的比较?

46、什么是扩展方法?

47、C#可否对内存直接操作

48、&和&&区别

49、as和is的区别

50、什么是匿名类,有什么好处?

51、什么是虚函数?什么是抽象函数?

52、什么是托管和非托管?

53、Lambda表达式?

54、如何提高.NET的性能 ?

55、EF

56、如何解决数据并发问题?

57、浅克隆与深克隆(浅拷贝与深拷贝)

58、.NET、C#和http://ASP.NEThttp://ASP.NET MVC 四者之间的区别

59、MVC 和三层框架区别

60、MVC 和三层框架区别 详细解释

61、高内聚,低耦合。

62、什么是WebService?

63、什么是Web API?

64、Web Service与Web API的关系?

65、前后端分离

66、{ get; set; }写法


1、ASP.NET页面之间传值方式?

  • Request.QueryString[“name”]

  • Request.Form(“name”)

  • Session

  • Cookie

  • Cache

  • Application

  • Server.Transfer

  • Database

  • HttpContext

2、如何理解装箱和拆箱?

当一个值类型转换为对象类型时,则被称为 装箱;==(值->对象)==

另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。==(对象->值)==

C#显式转换和隐式转换?

类型转换从根本上说是类型铸造,或者说是把数据从一种类型转换为另一种类型。

在 C# 中,类型铸造有两种形式:

  • 隐式类型转换 - 这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。例如,从小的整数类型转换为大的整数类型,从派生类转换为基类。
  • 显式类型转换 - 显式类型转换,即强制类型转换。显式转换需要强制转换运算符,而且强制转换会造成数据丢失。

装、拆过程详解

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

(1)第一步:新分配托管堆内存(大小为值类型实例大小加上一个方法表指针。

(2)第二步:将值类型的实例字段拷贝到新分配的内存中。

(3)第三步:返回托管堆中新分配对象的地址。这个地址就是一个指向对象的引用了。

拆箱:检查对象实例,确保它是给定值类型的一个装箱值。将该值从实例复制到值类型变量中。

在装箱时是不需要显式的类型转换的,不过拆箱需要显式的类型转换。

3、C#中什么是值类型与引用类型?

值类型:struct、enum、int、float、char、bool、decimal

引用类型:class、delegate、interface、array、object、string

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

class:可以被实例化,属于引用类型,

可以实现接口和单继承其他类,还可以作为基类型,

分配在内存的上的。

堆(heap)也被称为优先队列,队列中允许的操作是 先进先出(FIFO),在队尾插入元素,在队头取出元素。而堆也是一样,在堆底插入元素,在堆顶取出元素。二叉树的衍生,有最小堆最大堆的两个概念,将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

img

struct:属于值类型,

不能作为基类型,但是可以实现接口,

不能声明默认构造函数,

分配在内存的上的。

栈(Stack)又名堆栈,作为一个 先进后出 的数据结构。(注意:这里的堆栈本身就是栈,只是换了个抽象的名字。)
它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

img

另外补充一个和堆栈比较相关的概念——队列

img
  • 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
  • 队列采用 先进先出 FIFO(first in first out),新元素(等待进入队列的元素)总是被插入到链表的尾部,而读取的时候总是从链表的头部开始读取。每次读取一个元素,释放一个元素。所谓的动态创建,动态释放。因而也不存在溢出等问题。由于链表由结构体间接而成,遍历也方便。

5、virtual 和 abstract

virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义。

6、简述 private、 protected、 public、 internal 修饰符的访问权限。

private : 私有成员, 在类的内部才可以访问 ,也就是类内部的函数等成员可以访问。

protected : 保护成员,该类内部和继承类中可以访问。

public : 公共成员,完全公开,没有访问限制。

internal: 当前程序集内可以访问。

精简回答:

(1)public 公有访问,不受任何限制。

(2)private 私有访问,只限于本类成员访问。

(3)protected 保护访问,只限于本类和子类访问。

(4)internal 内部访问,只限于当前程序集内访问。

7、C#中堆和栈的区别? 值类型 栈 引用类型 堆 上学的时候常常讲

栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。

堆:一般由程序员分配释放。用 new、malloc等分配内存函数分配得到的就是在堆上。

存放在栈中时要管存储顺序,保持着先进后出的原则,他是一片连续的内存域,有系统自动分配和维护;

堆:是无序的,他是一片不连续的内存域,有用户自己来控制和释放,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC)来回收。

栈内存无需我们管理,也不受GC管理。当栈顶元素使用完毕,立马释放。而堆则需要GC清理。

补充:使用引用类型的时候,一般是对指针进行的操作而非引用类型对象本身。但是值类型则操作其本身

8、在ASP.NET中所有的自定义用户控件都必须继承自?

Control类

9、在.NET托管代码总我们不必担心内存泄漏,这是因为有了?

GC 垃圾收集器。

10、GC(Garbage Collection)

当程序需要更多的堆空间时,GC需要进行垃圾清理工作,暂停所有线程,找出所有无被引用的对象,进行清理,并通知栈中的指针重新指向地址排序后的对象。

GC只能处理 托管内存资源 的释放,对于 非托管资源则 不能使用GC进行回收,必须由程序员手动回收

例如FileStream或SqlConnection需要调用Dispose进行资源的回收。

精简:

GC,垃圾回收器,用于自动回收托管堆中无效对象的内存,释放内存空间。

11、CLR(Common Language Runtime)

公共语言运行库,负责资源管理(包括内存分配、程序及加载、异常处理、线程同步、垃圾回收等),并保证应用和底层操作系统的分离。

12、静态构造函数

最先被执行的构造函数,且在一个类里只允许有一个无参的静态构造函数

执行顺序:静态变量>静态构造函数>实例变量>实例构造函数

13、文件I/O

通过流的方式对文件进行读写操作

(1)FileStream

(2)StreamReader/StreamWriter

14、序列化与反序列化

序列化:将对象状态转换为可保持或传输的格式的过程。将对象实例的字段及类的名称转换成字节流,然后把字节流写入数据流

反序列化:将流转换为对象。

这两个过程结合起来,可以轻松地存储和传输数据。

15、线程同步

(1)方法一:阻塞(调用Sleep()或Join())

(2)方法二:加互斥锁lock

(3)方法三:信号和句柄(AutoResetEvent/ManualResetEvent,调用Set()和WaitOne())

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

相同点:

(1)都可以被继承

(2)都不能被实例化

(3)都可以包含方法的声明

不同点:

(1)抽象类被子类继承;接口被类实现

(2)抽象类只能被单个类继承;接口可继承接口,并可多继承接口

(3)抽象基类可以定义字段、属性、方法实现;接口只能定义属性、索引器、事件、和方法声明,不能包含字段

(4)抽象类可以做方法声明,也可做方法实现;接口只能做方法声明

(5)具体派生类必须覆盖(override)**抽象基类的抽象方法**;派生类必须实现接口的所有方法

(6)抽象类是一个不完整的类,需要进一步细化;接口是一个行为规范,必须按照规范来实现。

(7)抽象类中的虚方法或抽象方法必须用public修饰;接口中的所有成员默认为public,不能有private修饰符

解释说明

abstract class

abstract 声明抽象类抽象方法,一个类中有抽象方法,那么这个类就是抽象类了。所谓的 抽象方法,就是不含主体 (即不提供实现方法),必须由继承者重写。因此,抽象类不可实例化,只能通过继承被子类重写。

interface 声明接口,只提供一些方法规约, 接口是一个行为规范,必须按照规范来实现。

在C#8之前的版本中不提供任何实现,在C#9版本也可以支持接口的实现;不能用public、abstract等修饰,无字段、常量,无构造函数

区别扩展:

1.interface中不能有字段,而abstract class可以有;

2.interface中不能有public等修饰符,而abstract class 可以有。

3.interface 可以实现多继承

17、using关键字的使用场景

(1)作为指令:用于导入其他命名空间中定义的类型或为命名空间创建别名 (引用命名空间

(2)作为语句:用于定义一个范围,在此范围的末尾将释放对象 (定义一个代码块

18、new关键字的使用场景

运算符:创建对象实例

修饰符:在派生类定义一个重名的方法,隐藏掉基类方法

约束:泛型约束定义,约束可使用的泛型类型

19、委托与事件

委托可以把一个方法作为参数传入另一个方法,可以理解为指向一个函数的引用;事件是一种特殊的委托。

比如:onclick事件中的参数就是一种方法。

20、重载(overload)与重写(override)的区别

重载:是方法的名称相同,参数或参数类型不同;重载是面向过程的概念。

重写:是对基类中的虚方法进行重写。重写是面向对象的概念。

21、return执行顺序

try{} 里有一个return语句,那么finally{} 里的code在return前执行。

22、switch(expression)

其中expression支持任何数据类型,包括null。

23、反射Reflection

动态获取程序集信息。

解释:

程序集包含模块,而模块又包括类型,类型下有成员,反射就是管理程序集,模块,类型的对象,它能够动态的创建类型的实例,设置现有对象的类型或者获取现有对象的类型,能调用类型的方法和访问类型的字段属性。

它是在运行时创建和使用类型实例。

扩展:

typeof

说反射之前,要先知道typeof这个关键字,它是反射的核心,typeof可以动态的获取某个类的类型信息,反射通过这些类型信息,就可以生成实例等一些操作。

Reflection

反射的命名空间位于System.Reflection

24、property与attribute的区别

property是属性,用于存取类的字段;

attribute是特性,用来标识类,方法等的附加性质。

25、(Class)和实例(Instance)

理解:

面向对象最重要的概念就是类(Class)和实例(Instance)

牢记:类是抽象的模板

比如 Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

类和类的实例有什么区别?

类是抽象概念,类的实例是具体的。

比如 创建一个类名字叫“学生”,实例化一个学生“张三”,张三就是“学生类”的一个实例。

比如创建类:

1
2
3
4
5
6
7
8
9
10
11
12
class Student //创建一个学生类

{

String name; //学生有个属性,叫“姓名”

}

Student s = new Student(); //创建一个学生类的对象,也就是将类实例化

s.name = "张三"; //将新创建的类的实例的属性“姓名”赋值为“张三”

类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;

方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;

26、C# 中static关键字的作用?

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

对类的实例 有意义的 字段 和 方法 不加static关键字,称为非静态成员或实例成员。

注: 静态字段在内存中只有一个拷贝,

非静态字段则是在每个实例对象中拥有一个拷贝。

而方法无论是否为静态,在内存中只会有一份拷贝,

区别只是通过类名来访问还是通过实例名来访问。

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

它们被称为常成员变量和常成员函数,又称为类成员变量和类成员函数。 分别用来反映类的状态。

比如类成员变量可以用来统计类实例的数量,类成员函数负责这种统计的动作。不用new

28、文件编码格式

阶段一:ASCII

阶段二:ANSI(本地化) 如:GBK、GB2312

阶段三:UNICODE(国际化) 如:UTF-8

29、值传递与引用传递解释?

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

引用传递时,系统不是将实参本身的值复制后传递给形参,而是将其引用值(即地址值)传递给形参,因此,形参所引用的该地址上的变量与传递的实参相同,方法体内相应形参值得任何改变将影响到作为引用传递的实参

简而言之,按值传递不是值参数是值类型,而是指形参变量会复制实参变量,也就是会在栈上多创建一个相同的变量。而按引用传递则不会。可以通过 ref 和 out 来决定参数是否按照引用传递。

浅显易懂解释:JAVA 方面的

值传递: 值传递是对基本型变量而言的,传递的是一个变量的副本,改变副本不影响原变量。

引用传递: 引用传递一般是对对象(引用)型变量而言的,传递的是该对象地址的一个副本,并不是原对象本身,所以引用对象进行操作时会改变原对象。

来自 请你解释什么是值传递和引用传递?

30、参数传递 ref 与 out 的区别

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

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

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

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

31.什么是内存泄漏?

答:一般我们所说的内存泄漏指的是堆内存的泄漏。

堆内存是程序从堆中为其分配的,大小任意的,使用完后要显示释放内存。

当应用程序用关键字new等创建对象时,就从堆中为它分配一块内存,使用完后程序调用free或者delete释放该内存,否则就说该内存就不能被使用,我们就说该内存被泄漏了。

32、跨域

跨域是指浏览器的不执行其他网站脚本的,由于浏览器的同源策略造成,是对JavaScript的一种安全限制。

说白点理解,当你通过浏览器向其他服务器发送请求时,不是服务器不响应,而是服务器返回的结果被浏览器限制了。

同源策略的同源

同源指的是协议、域名、端口 都要保持一致。

http://www.123.com:8080/index.html (http协议,www.123.com 域名、8080 端口 ,只要这三个有一项不一样的都是跨域,这里不一一举例子)

http://www.123.com:8080/matsh.html(不跨域)

http://www.123.com:8081/matsh.html(端口不一样,跨域)

注意:localhost 和127.0.0.1 虽然都指向本机,但也属于跨域。

跨域的解决方案

>JSONP方式,只支持GET请求,不支持POST请求。

>反向代理,Nginx

> 配置浏览器(我配置了谷歌,属性->目标> 在后面追加 –args –disable-web-security –user-data-dir 注意有个空格)。设置成功打开浏览器是出现已栏提示证明已成功配置。

来自 <https://www.cnblogs.com/yflbk-2016/p/12603666.html>

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

延迟加载(Lazy Loading)只在真正需要进行数据操作的时候再进行加载数据,可以减少不必要的开销。

34、简述Func与Action的区别?

Func是有返回值的委托,Action是没有返回值的委托。

35、能用foreach遍历访问的对象的要求?

需要实现IEnumerable接口或声明GetEnumerator方法的类型。

36、什么是泛型?

即通过参数化类型来实现在同一份代码上操作多种数据类型。

泛型就是不确定类型的,被调用时才指定类型的数据类型。

来自 <https://www.cnblogs.com/netchaozhuai/p/13395827.html>

37、Final

final修饰符来限定变量、字段、方法和类。

用于变量时,该变量只能赋值一次,不可修改;

用于方法时,该方法不能被重写或隐藏;

用于类时,该类不能被继承。

来自 <https://blog.csdn.net/weixin_34326179/article/details/90123166>

38、数据库操作的相关类

特定类:Connection,Command,CommandBuilder,DataAdapter,DataReader,Parameter,Transaction

共享类:DataSet,DataTable,DataRow,DataColumn,DataRealtion,Constraint,DataColumnMapping,DataTableMapping

39、ADO.NET 五大对象

(1)Connection:开启程序与数据库之间的连接。

(2)Command:对数据库发送一些指令。例如增删改查等指令,以及调用存在数据库中的存储过程等。

(3)DataAdapter:主要在数据源及DataSet 之间执行传输工作,通过Command 下达命令后,将取得的数据放进DataSet对象中。

DataAdapter对象是用来读取数据库,可读取写入数据;但他占用内存比DataReader大,速度慢。

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

备注:将DataAdapter对象当做DataSet 对象与数据源间传输数据的桥梁。

DataSet包含若干DataTable、DataTableTable包含若干DataRow。

(5)DataReader:DataReader对象是用来读取数据库的最简单方式,只能读取,不能写入,并且是从头至尾往下读的,无法只读某条数据;但他占用内存小,速度快。

总结:http://ADO.NET 使用Connection对象来连接数据库,使用Command或DataAdapter对象来执行SQL语句,并将执行的结果返回给DataReader或DataAdapter,然后再使用取得的DataReader或DataAdapter对象操作数据结果。

详细解释:

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

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

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

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

DataSet是放在内存中的。DataSet 的能力不只是可以储存多个Table 而 已,还可以透过DataAdapter对象取得一些例如主键等的数据表结构,并可以记录数据表间的关联。 DataSet 对象可以说是http://ADO.NET 中重量级的对象,这个对象架构在DataAdapter对象上,本身不具备和 数据源沟通的能力;也就是说我们是将DataAdapter对象当做DataSet 对象以及数据源间传输数据的桥 梁。DataSet包含若干DataTable、DataTableTable包含若干DataRow。

DataReader:当我们只需要循序的读取数据而不需要其它操作时,可以使用DataReader 对象。 DataReader对象只是一次一次向下循序的读取数据源中的数据,这些数据是存在数据库服务器中的,而 不是一次性加载到程序的内存中的,只能(通过游标)读取当前行的数据,而且这些数据是只读的,并 不允许作其它的操作。因为DataReader 在读取数据的时候限制了每次只读取一条,而且只能只读,所 以使用起来不但节省资源而且效率很好。使用DataReader 对象除了效率较好之外,因为不用把数据全 部传回,故可以降低网络的负载。

==40、C# DataTable和DataSet 区别?==

可以把DataTable和DataSet看做是数据容器,查询数据库后得到一些结果,放到这种容器里。

为什么用容器?原因是,容器的功能强大,除了存数据,还可以有更大用途。

举例:在一个c/s结构的桌面数据库系统里,你可以把前面存放查询结果的容器里的数据显示到你客户端界面上,用户在界面上对数据进行添加、删除、修改,你可以把用户的操作更新到容器,等用户操作完毕了,要求更新,然后你才把容器整个的数据变化更新到中心数据库,这样做的好处是什么?就是减少了数据库操作,客户端速度提高了,数据库压力减小了。

DataSet可以比作一个内存中的数据库,DataTable是一个内存中的数据表,DataSet里可以存储多个DataTable。

DataSet:数据集。一般包含多个DataTable,用的时候,dataset[“表名”]得到DataTable

DataTable:数据表。

DataSet对象中的Tables的用法

  • DataSet是一个数据集合,DataSet.Tables是一个存放Data Table的数组,当adapter.Fill(dataSet);

  • 执行后,程序会通过SQL引擎返回一个结果集存放在内存中,这个结果集就是一个DataTable,并且这个DataTalbe会被添加到DataSet.Tables中,所以==dataSet.Tables[0]就是返回所要查询的结果集。==

1
string rid=table.Row[0]["rid"].ToString();   //table.Rows[0]表示Table的第一行数据,table.Rows[0]["rid"].ToString()表示talbe中列rid的值,table的所有列式在SQL中所查询的所有列

一个DataSet中有很多DataTable,用DataTabeles表示,默认填充第一个,集DataTables[0]。

1
2
3
4
5
6
table.Rows------表示所有行

table.Rows[0]--------第一行

table.Row[0]["rid"]---------第一行名称为“rid”的列。

41、索引器(Indexers)

解释:C# 类的索引器(indexer)。简单说来,所谓索引器就是一类特殊的属性,通过它们你就可以像引用数组一样引用自己的类。

显然,这一功能在创建集合类的场合特别有用,而在其他某些情况下,比如处理大型文件或者抽象某些有限资源等,能让类具有类似数组的行为当然也是非常有用的。

无需显式指定类型或实例成员,即可设置或检索索引值。 索引器类似于属性,不同之处在于它们的访问器需要使用参数。

微软官网示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class SampleCollection<T>

{

// Declare an array to store the data elements.

private T[] arr = new T[100];

// Define the indexer to allow client code to use [] notation.

public T this[int i]

{

get { return arr[i]; }

set { arr[i] = value; }

}

}

class Program

{

static void Main(string[] args)

{

var stringCollection = new SampleCollection<string>();

stringCollection[0] = "Hello, World";

Console.WriteLine(stringCollection[0]);

}

}

42、POST和GET深入理解

\1. POST和GET都是向服务器提交数据,并且都会从服务器获取数据。

\2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。

post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。

\3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。

\4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。

\5. get安全性非常低,post安全性较高。但是执行效率却比Post方法好。

建议:

1、get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;

2、在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式;

区别:

1、传送方式:get通过地址栏传输,post通过报文传输。

2、传送长度:get参数有长度限制(受限于url长度),而post无限制

3、GET和POST还有一个重大区别,简单的说:

GET产生一个TCP数据包;POST产生两个TCP数据包

43、C#中用sealed修饰的类有什么特点?

密封,不能继承。

44、string和StringBuilder的区别,两者性能的比较?

都是引用类型,

分配再堆上 StringBuilder默认容量是16,可以允许扩充它所封装的字符串中字符的数量。

每个StringBuffer对象都有 一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。

对于简单的字符串连接操作,在性能上stringbuilder不一定总是优于strin因为stringbulider对象的创建也消耗大量的性能。

在字符串连接比较少的情况下,过度滥用stringbuilder会导致性能的浪费而非节约,只有大量无法预知次数的字符串操作才考虑stringbuilder的使用。

从最后分析可以看出如果是相对较少的字符串拼接根本看不出太大差别。

Stringbulider的使用,最好制定合适的容量值,否则优于默认值容量不足而频繁的进行内存分

补充:

string 每次内容发生变化,都会生成一个新对象,重新分配内存

stringbuilder 每次操作都是对自身进行操作,而不是生成新的对象

45、什么是扩展方法?

一句话解释,扩展方法使你能够向现有类型“添加”方法,

无需修改类型条件:按扩展方法必须满足的条件,

1.必须要静态类中的静态方法

2.第一个参数的类型是要扩展的类型,并且需要添加this关键字以标识其为扩展方法

建议:通常,只在不得已的情况下才实现扩展方法,并谨慎的实现

使用:不能通过类名调用,直接使用类型来调用

46、C#可否对内存直接操作

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

47、&和&&区别

相同点

&和&&都可作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,其结 果才为true,否则,只要有一方为false,则结果为false。(ps:当要用到逻辑与的时候&是毫无意义, &本身就不是干这个的)

不同点

if(loginUser!=null&&string.IsnullOrEmpty(loginUser.UserName)) &&具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,对于上面的表达式,当 loginUser为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则 会抛出NullPointerException异常。(ps:所以说当要用到逻辑与的时候&是毫无意义的) & 是用作位运算的。

总结

&是位运算,返回结果是int类型 &&是逻辑运算,返回结果是bool类型。

48、as和is的区别

as在转换的同时判断兼容性,如果无法进行转换,返回位null(没有产生新的对象),as转换是否成功 判断的依据是是否位null。

is只是做类型兼容性判断,并不执行真正的类型转换,返回true或false,对象 为null也会返回false。

as比is效率更高,as只需要做一次类型兼容检查。

49、什么是匿名类,有什么好处?

不用定义、没有名字的类,使用一次便可丢弃。好处是简单、随意、临时的。

50、什么是虚函数?什么是抽象函数?

虚函数:没有实现的,可以由子类继承并重写的函数。

抽象函数:规定其非虚子类必须实现的函数,必须被重写。

51、什么是托管和非托管?

托管代码:是由公共语言运行库(CLR)执行的代码,而不是由操作系统直接执行。有关内存管理(内存申请,内存释放,垃圾回收之类的)全部都是.net的CLR来管理。

非托管代码:直接编译成目标计算机码,由操作系统直接执行的代码,内存回收要继承IDisposable接口手动回收。

52、Lambda表达式?

“Lambda表达式”是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量。

53、如何提高.NET的性能 ?

1、使用异步方式调用Web服务和远程对象

解释:只要有可能就要避免在请求的处理过程中对Web服务和远程对象的同步调用,因为它占用的是的 http://ASP.NET 线程池中的工 作线程,这将直接影响Web服务器响应其它请求的能力。

2、使用适当的Caching策略来提高性能

3、判断字符串,不要用”” 比较。

//避免 if(strABC!=null && strABC!=””) {}

//推荐 if(!strABC.IsNullOrEmpty) {}

4、页面优化

5、用完马上关闭数据库连接

6、尽量使用存储过程,并优化查询语句

7、只读数据访问用SqlDataReader,不要使用DataSet托管堆中

54、EF

1、EF(Entity Framework)

实体框架EF是http://ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架。

Database First

Database First”模式我们称之为“数据库优先”,前提是你的应用已经有相应的数据库,你可以使用EF设计工具根据数据库生成数据数据类,你可以使用Visual Studio模型设计器修改这些模型之间对应关系。

来自 <https://blog.csdn.net/u011854789/article/details/72783902>

Model First

Model First我们称之为“模型优先”,这里的模型指的是“http://ADO.NET Entity Framework Data Model”,此时你的应用并没有设计相关数据库,在Visual Studio中我们通过设计对于的数据模型来生成数据库和数据类。

来自 <https://blog.csdn.net/u011854789/article/details/72783902>

Code First

Code First模式我们称之为“代码优先”模式,是从EF4.1开始新建加入的功能。使用Code First模式进行EF开发时开发人员只需要编写对应的数据类(其实就是领域模型的实现过程),然后自动生成数据库。这样设计的好处在于我们可以针对概念模型进行所有数据操作而不必关心数据的存储关系,使我们可以更加自然的采用面向对象的方式进行面向数据的应用程序开发。

来自 <https://blog.csdn.net/u011854789/article/details/72783902>

2、什么是ORM?

ORM指的是面向对象的对象模型和关系型数据库的数据结构之间的互相转换。

(表实体跟表之间的相互转换)

ORM框架有很多,EF框架是ORM框架的其中一种,是实现了ORM思想的框架。

O=>表实体

M=>映射关系

R=>数据库.表

来自 <https://blog.csdn.net/qq_35491254/article/details/52994136>

55、如何解决数据并发问题?

一:并发操作出现的原因

原因:多个动作在一瞬间同时操作同一数据

现象:

  1. 多人在某一瞬间通过相同的方式操作同一条数据
  2. 多人在某一瞬间通过不同的方式操作同一条数据
  3. 在某一瞬间,同一动作,多次执行

二:并发举例及解决办法

针对上述的三种的情况,分别以实际情况进行举例。

【多人在某一瞬间通过相同的方式操作同一条数据】

1.某仓库系统有一品牌商品A,商品A在数据库中只允许存在一条记录,库存的数量是这条数据的一个字段,现有库存100件,在某一天到货了1000件。由于数量比较大,现在需要10名操作员去处理这1000件商品进行入库,操作的途径都是使用PDA扫描完成后进行入库。我们假设至少存在1名以上的操作员同时进行入库操作。这样就可以满足上述条件【多人在某一瞬间通过相同的方式操作同一条数据】。在这种情况下,如果不进行处理,就会导致数据错乱,错乱的原因简单说就是在双方写数据时没有获取到最新的数据库数据。

解决方法:

方法一: 加锁。加锁是比较常用的方法。从系统的架构上来说,锁被分为单机锁和分布式锁。如果系统只是部署在单一机器上,可以简单通过java提供的各种锁来进行操作。如果系统被部署在多台机器上,可以使用redis来实现分布式加锁。这两种加锁方式从某种意义上来说是悲观锁。上述的问题,我们可以使用商品的唯一属性,比如id或者商品的唯一条码来进行加锁。

方法二:数据库乐观锁。数据库乐观锁几乎适用于所有的并发场景。使用方法:在数据库表中增加一个版本号字段,每一次更新和删除时把当前持有的对象版本号和数据库中最新的版本号进行比对,如果相同则验证通过,不然则操作失败。

方法三:使用消息队列。这种方式在消息过多时,对库存的处理可能不会特别及时。由于库存一般是需要比较及时的可见,所以这种方式并不建议。

【多人在某一瞬间通过不同的方式操作同一条数据】

\2. 还是按照上述的背景来说。在这10名操作员进行入库的同时,还有至少1名操作员对A商品进行出库操作。我们假设入库时没有并发问题,但是其中一个入库和一个出库同时操作了A商品的库存,通过两种不同的方式对库存进行操作。如果不进行处理,库存也会出现数据错乱的问题。

解决方法:

方法一: 加锁。这个时候使用普通的单机锁已经没有意义了,可以使用分布式锁,依旧使用唯一属性来进行加锁,尽管方法不同,但关键的key是一样的,这样就可以锁住操作。

方法二:数据库乐观锁。

对于上述的问题,我扩展一下,如果是一批商品,你总不能一个一个进行加锁处理吧,那样效率也太低了。所以这种情况下,简单的加锁已经不能满足现在的需要了。所以数据库乐观锁又重新出现了。在批量更新时,发现其中任何一个商品的版本号不一致,立即报错回滚。

【在某一瞬间,同一动作,多次执行】

3.这一种情况属于请求重复提交,同样,如果没有进行处理,数据也会出现问题。

一个用户在入库时重复提交了两次,这样在不考虑其它并发的影响下,库存中的数据会多增加一次,但在入库历史中却只能看见一次记录,这样肯定是不可接受的。

解决方法:

方法一:前台可以在按钮或链接第一次点击后立刻禁用。这样可以有效的解决绝大部分的问题。但是由于操作端千变万化,这种方式并不能够完全解决问题。

方法二:后台生成一个随机数放在前台,前台在访问后台时,将随机数传输到后台进行验证,第一次验证通过即刻销毁, 随机数可以存在redis或session中,一般用于表单提交。但是这种方式还是存在缺陷,如果同一个页面有多个请求,一个随机数就完全不够用了。

方法三:nginx可以控制ip在同一时间内对服务的访问频率。比如入库时,如果进行了多次点击,发送了多次请求,在这1秒中,系统只接收第一次请求。

三:总结

处理并发的最终原理其实就是:将用户的并行操作变成串行操作。

在解决并发问题时,从操作端到服务端,再到数据库,都需要进行处理,层层过滤。

前端:防止多次点击。

服务端:对相同数据的操作写在同一个服务中。

数据库:乐观锁一定要使用。有需要的话,数据库的联合唯一索引也要准备。

来自 <https://blog.csdn.net/love1793912554/article/details/92437035>

56、.NET、C#和http://ASP.NET,http://ASP.NET MVC 四者之间的区别

什么是.NET?

.NET是微软公司下的一个开发平台,.NET核心就是.NET Framwork(.NET框架)是.NET程序开发和运行的环境,在这个平台下可以用不同的语言进行开发。

因为.NET是跨语言的一个平台。语言可以是C#,f#,j#,http://vb.net等等。

顺便说一下sum公司的JAVA和.NET不同的一点是java是跨平台的,不跨语言的。.NET跨平台仅限于安卓系统和IOS苹果系统。

1、.net框架的组成分为两部分:

CLR:公共语言运行时 (提供内在管理,代码安全性检测等功能)

FLC:.NET框架类库,类库中有很多线程的资源可使用(比如:类,方法,属性),提供大量应用类库,提高开发效率。

2、CLR的结构:

CTS:通用类型系统,将各种语言中的数据类型转换成统一的类型。

CLS:通用语言规范,获取各种语言转换成统一的语法规范。

JIT:实时编译器(即时编译器)用于将转换之后的语言编译为二进制语言,交给CPU执行。

3、NET运行机制流程:

各种语言(c#,F#,j#等对应的源程序)———> 经过CTS,CLS第一次编译 ———> 统一规范语言(中间语言)MSIL(.EXE,.DLL)

———> JIT第二次编译 ———> 二进制语言 ———> 运行在CPU中

Java运行机制

.java———>编译———>字节码文件(.CLASS)———> jvm解释(jvm虚拟机)———> 二进制语言———>运行在CPU中

4.C#是一个.NET平台下的一个程序设计语言,只是一个语言,仅此而已。

程序设计语言是为了方便开发人员和计算机沟通的工具。

程序设计语言是为了方便开发人员和计算机沟通的工具。

ASP.NET是一个网站开发的技术,是.NET框架中的一个应用模型。(历史挺长远的)使用ASP.NET开发Web应用程序并维持其运行,比其他开发语言更加简单。

与Java、PHP和Perl等高级技术相比,ASP.NET具有方便性、灵活性、生产效率高、安全性高及面向对象等优点,是目前主流的网络编程技术之一。

6.ASP.NET MVC,刚开始接触这个技术的时候我经常不理解他们的名字,我相信许多学ASP.NET开发人员开始接触MVC应该也和我一样产生很多为什么,也会误认为认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,深入学习后我才知道事实上ASP.NET是创建WEB应用的框架MVC是能够用更好的方法来组织并管理代码的一种更高级架构体系,所以可以称之为ASP.NET MVC。

我们可将原来的ASP.NET称为 ASP.NET Webforms,新的MVC 称为ASP.NET MVC。

MVC是软件架构的一种模式,可以说就相当于我们常说的设计模式吧。其中主要包括三个模块,顾名思义。

就如MVC名字所显示的那样:

模型(Model),视图(View),控制器(Controller)。

mvc中的模型(Model)和视图(View )是完全区别于三层架构中的模型(Model)和视图(View)的。

MVC中模型(Model)的特点:

①有对数据直接访问的权利,如:对数据库的访问;

②模型(Model)“不依赖”视图(View)和控制器(Controller),即模型(Model)不关心它会被如何显示或者如何被操作;

③模型(Model)中数据的变化一般会通过一种刷新机制被“公布”;

④为了实现③中的“机制”用于监视此模型的视图必须事先在此模型上注册。从而,视图可以了解在数据模型上发生的改变。

视图(View),这里的视图基本跟三层中的视图一样,都是为了显示数据,没有程序上的逻辑。为了实现视图上数据的刷新,视图(View)需要访问它监视的模型(Model),所以应该事先在被它监视的数据那里进行注册。

控制器(Controller),这个概念是在三层中不存在的概念。它主要起到不同层面的组织作用,用于控制应用程序的流程。主要处理事件并作出相应操作。

来自 https://www.cnblogs.com/wwym/p/5555772.html

58、MVC 和三层框架区别

意思

M 即Model(模型层),主要负责处理业务逻辑以及数据库的交互

V 即View(视图层),主要负责显示数据和提交数据

C 即Controller(控制层),主要是永作辅助捕获请求并控制请求转发

三层

UI界面层

BLL业务逻辑层

DAL数据访问层

区别

三层是基于业务逻辑来分的,而MVC是基于页面来分的

MVC模式是一种复合 设计模式,一种解决方案

三层是种 软件架构,通过接口实现编程

三层模式是体系结构模式,MVC是设计模式

三层模式又可归于部署模式,MVC可归于表示模式

来自 https://www.cnblogs.com/yellowwenhao/p/11542367.html

59、MVC 和三层框架区别 详细解释

三层架构是一个分层式的软件体系架构设计,它可适用于任何一个项目。

MVC是一个设计模式,它是根据项目的具体需求来决定是否适用于该项目。

那么架构跟设计模式有什么区别呢?

我们从接手一个项目开始,首先,我们需要进行架构设计,一般我们采用的就是分层式的架构设计,即我们的三层架构。

然后,在确定了架构以后,我们再根据项目的具体需求去考虑是否需要应用一些设计模式,比如是否应用我们的MVC模式,抽象工厂模式等等。(在这里我们看出,MVC与三层架构不是一个等级的,而与抽象工厂等设计模式才是一路的)

最后,确定了模式以后,就是我们的一些具体的实现了。(当然一个项目不仅仅考虑这些问题,我只是为了说明两者的区别,将其他问题已省略)

其次,它俩划分的层次不同。

三层架构将整个项目划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。

MVC 是在三层UI层上 进一步划分 即Model(模型),View(视图),Controller(控制)。

区别与联系\

  • 字面解释

    我们平常所说的V是UI,C是BLL,M是DAL的观点是错误的。

    而我们通常所见到的MVC一般也都是在应用三层架构的基础上,即将Model层再进行分层。

    而如果Model不再进行划分的话,那么使用MVC的意义也就不大了。

  • 各自目的:

    然后,它俩的目的着重点不同。

    三层架构的目的着重点是“高内聚,低耦合”,即解耦。

    MVC的目的则是实现Web系统的职能分工,即职责划分。

    其实职责划分也是解耦,但是三层侧重的是整体的一个解耦,而MVC侧重的是web系统的解耦,即侧重jsp和Servlet的一个解耦。

为何我们会将其混为一谈?

1.二者都是“三层”

这个原因是最容易迷惑我们初学者的,一个是UI,BLL,DAL,一个是View,Controller,Model,不都是三层吗?

虽然都是“三层”(不一定是真的三层,还可以是多层),但是它们的划分的不一样。大家可从上面的图中看出不同。

2.MVC总是伴随着三层架构。

这个就是我在前面一再强调的,我们一般是在考虑使用(也可以不使用)了三层架构的基础上再根据具体需求决定是否需要使用MVC,于是我们常说的MVC中总是伴随着三层架构,所以大家总是会认为MVC就是三层架构,三层架构就是MVC,殊不知,它们二者是一起出现的。

3.都是在分层,即都是在解耦。

前面说它们目的的时候也说了,虽然它们的侧重点不同,但是它们的总体目的是一样的,都是为了解耦,对于初学者而言,是不知道这两个侧重点有何不同的。

大家往往对它们的联系知道很多,不然也不会混为一谈,但是对它们的区别却知道较少,希望我上面讲解的它们两者之间的区别可以让大家对它们有些了解,如有写的不妥的地方,请指教。

三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:

表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。

区分层次的目的即为了“高内聚,低耦合”的思想。

1、表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得。

2、业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。

3、数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找等。

MVC是 Model-View-Controller,严格说这三个加起来以后才是三层架构中的UI层。

也就是说,MVC把三层架构中的UI层再度进行了分化,分成了控制器、视图、实体三个部分。

控制器完成页面逻辑,通过实体来与界面层完成通话;而C层直接与三层中的BLL进行对话。

MVC可以是三层中的一个表现层框架,属于表现层。三层和MVC可以共存。

三层是基于业务逻辑来分的,而MVC是基于页面来分的。

MVC主要用于表现层,3层主要用于体系架构,3层一般是表现层、中间层、数据层,其中表现层又可以分成M、V、C,(Model View Controller)模型-视图-控制器

MVC是表现层的架构,MVC的Model实际上是ViewModel,即供View进行展示的数据。 ViewModel不包含业务逻辑,也不包含数据读取。

三层架构的分层模式是典型的上下关系,上层依赖于下层。

但MVC作为表现模式是不存在上下关系的,而是相互协作关系。

即使将MVC当作架构模式,也不是分层模式。MVC和三层架构基本没有可比性,是应用于不同领域的技术。

https://www.cnblogs.com/zdxster/p/5305155.html

60、高内聚,低耦合。

内聚关注 模块 内部元素 结合程度,

耦合关注 模块 间 依赖程度。

需要知道!!!

内聚性:

又称块内联系。

指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。

所谓高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。

耦合性:

也称块间联系。

指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。

对于低耦合,粗浅的理解是:一个完整的系统,模块与模块之间,尽可能的使其独立存在。也就是说,让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。这样有利于修改和组合。

更深层次!!!

内聚

内聚有如下的种类,它们之间的内聚度由弱到强排列如下:

一、偶然内聚:一个模块内的各处理元素之间没有任何联系,只是偶然地被凑到一起。这种模块也称为巧合内聚,内聚程度最低。

二、逻辑内聚:这种模块把几种相关的功能组合在一起, 每次被调用时,由传送给模块参数来确定该模块应完成哪一种功能 。

三、时间内聚:把需要同时执行的动作组合在一起形成的模块称为时间内聚模块。

四、过程内聚:构件或者操作的组合方式是,允许在调用前面的构件或操作之后,马上调用后面的构件或操作,即使两者之间没有数据进行传递。简单的说就是如果一个模块内的处理元素是相关的,而且必须以特定次序执行则称为过程内聚。

例如某要完成登录的功能,前一个功能判断网络状态,后一个执行登录操作,显然是按照特定次序执行的。

五、通信内聚:指模块内所有处理元素都在同一个数据结构上操作或所有处理功能都通过公用数据而发生关联(有时称之为信息内聚)。即指模块内各个组成部分都使用相同的数据结构或产生相同的数据结构。

六、顺序内聚:一个模块中各个处理元素和同一个功能密切相关,而且这些处理必须顺序执行,通常前一个处理元素的输出时后一个处理元素的输入。

例如某要完成获取订单信息的功能,前一个功能获取用户信息,后一个执行计算均价操作,显然该模块内两部分紧密关联。

顺序内聚的内聚度比较高,但缺点是不如功能内聚易于维护。

七、功能内聚:模块内所有元素的各个组成部分全部都为完成同一个功能而存在,共同完成一个单一的功能,模块已不可再分。即模块仅包括为完成某个功能所必须的所有成分,这些成分紧密联系、缺一不可。

功能内聚是最强的内聚,其优点是它的功能明确。判断一个模块是否功能内聚,一般从模块名称就能看出。如果模块名称只有一个动词和一个特定的目标(单数名词),一般来说就是功能内聚,如:“计算水费”、“计算产值”等模块。功能内聚一般出现在软件结构图的较低层次上。

功能内聚模块的一个重要特点是:他是一个“暗盒”,对于该模块的调用者来说,只需要知道这个模块能做什么,而不需要知道这个模块是如何做的。

耦合

耦合可以分为以下几种,它们之间的耦合度由高到低排列如下:

一、 内容耦合:一个模块直接访问另一模块的内容,则称这两个模块为内容耦合。

若在程序中出现下列情况之一,则说明两个模块之间发生了内容耦合:

\1. 一个模块直接访问另一个模块的内部数据。

\2. 一个模块不通过正常入口而直接转入到另一个模块的内部。

\3. 两个模块有一部分代码重叠(该部分代码具有一定的独立功能)。

\4. 一个模块有多个入口。

内容耦合可能在汇编语言中出现。大多数高级语言都已设计成不允许出现内容耦合。这种耦合的耦合性最强,模块独立性最弱。

二、公共耦合:一组模块都访问同一个全局数据结构,则称之为公共耦合。公共数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。如果模块只是向公共数据环境输入数据,或是只从公共数据环境取出数据,这属于比较松散的公共耦合;如果模块既向公共数据环境输入数据又从公共数据环境取出数据,这属于较紧密的公共耦合。

公共耦合会引起以下问题:

\1. 无法控制各个模块对公共数据的存取,严重影响了软件模块的可靠性和适应性。

\2. 使软件的可维护性变差。若一个模块修改了公共数据,则会影响相关模块。

\3. 降低了软件的可理解性。不容易清楚知道哪些数据被哪些模块所共享,排错困难。

一般地,仅当模块间共享的数据很多且通过参数传递很不方便时,才使用公共耦合。

三、外部耦合:一组模块都访问同一全局简单变量,而且不通过参数表传递该全局变量的信息,则称之为外部耦合。

四、控制耦合:模块之间传递的不是数据信息,而是控制信息例如标志、开关量等,一个模块控制了另一个模块的功能。

五、标记耦合:调用模块和被调用模块之间传递数据结构而不是简单数据,同时也称作特征耦合。表就和的模块间传递的不是简单变量,而是像高级语言中的数据名、记录名和文件名等数据结果,这些名字即为标记,其实传递的是地址。

六、数据耦合:调用模块和被调用模块之间只传递简单的数据项参数。相当于高级语言中的值传递。

七、非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。耦合度最弱,模块独立性最强。

分析

高内聚,低耦合的系统有什么好处呢?

事实上,短期来看,并没有很明显的好处,甚至短期内会影响系统的开发进度,因为高内聚,低耦合的系统对开发设计人员提出了更高的要求。

高内聚,低耦合的好处体现在系统持续发展的过程中,高内聚,低耦合的系统具有更好的重用性,维护性,扩展性,可以更高效的完成系统的维护开发,持续的支持业务的发展,而不会成为业务发展的障碍

高内聚低耦合是否意味着内聚越高越好,耦合越低越好?

  1. 并不是内聚越高越好,耦合越低越好,真正好的设计是在高内聚和低耦合间进行平衡,也就是说高内聚和低耦合是冲突的。
  2. 最强的内聚莫过于一个类只写一个函数,这样内聚性绝对是最高的。但这会带来一个
    明显的问题:类的数量急剧增多,这样就导致了其它类的耦合特别多,于是整个设计就变成了“高内聚高耦合”了。由于高耦合,整个系统变动同样非常频繁。
  3. 对于耦合来说,最弱的耦合是一个类将所有的函数都包含了,这样类完全不依赖其它类,耦合性是最低的。但这样会带来一个明显的问题:内聚性很低,于是整个设计就变成了“低耦合低内聚”了。由于低内聚,整个类的变动同样非常频繁。
  4. 真正做到高内聚、低耦合是很难的,很多时候未必一定要这样,更多的时候“最适合”的才是最好的,不过、审时度势、融会贯通、人尽其才、物尽其用,才是设计的王道。

软件设计时,如何做好高内聚低耦合?

在模块划分时,要遵循“一个模块,一个功能”的原则,尽可能使模块达到功能内聚。

耦合是影响软件复杂程度和设计质量的一个重要因素,为提高模块的独立性,应建立模块间尽可能松散的系统,在设计上我们应采用以下原则:若模块间必须存在耦合,应尽量使用数据耦合,少用控制耦合,慎用或有控制地使用公共耦合,并限制公共耦合的范围,尽量避免内容耦合。

来自 <https://blog.csdn.net/walid1992/article/details/73278304>

61、什么是ABP框架?

ABP框架全称为“http://ASP.NET Boilerplate Project”,中文翻译为“ http://ASP.NET样板项目”,诞生的主要目的就是为了让.NET程序员“秒变”架构师,将.NET企业级项目的主流开发技术、最先进的架构整合起来,让.NET工程师能够更快的开发出更好的项目。

62、什么是WebService?

WebService是一种跨编程语言和跨操作系统平台的远程调用技术。

WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过

Internet进行基于Http协议的网络应用间的交互。

63、什么是Web API?

Web API是网络应用程序接口。

包含了广泛的功能,网络应用通过API接口,可以实现存储服务、消息服务、计算服务等能力,利用这些能力可以进行开发出强大功能的web应用。

64、Web Service与Web API的关系?

\1. webservice走HTTP协议和80端口。WebService则类似于bs架构,只需要开发服务器端,不需要开发客户端,客户端只要遵循soap协议,就可以调用。

\2. api,用的协议和端口,是根据开发人员定义的。 api类似于cs架构,需要同时开发客户端API和服务器端程序。

webapi用的是http协议,webservice用的是soap协议

webapi无状态,相对webservice更轻量级。webapi支持如get,post等http操作

http soap关系

http:是一个客户端和服务器端请求和应答的标准(TCP)。http协议其目的是为了提供一种发布和接收htttp页面的方法

一http协议的客户端与服务器的交互:由HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端发送过来的请求。一旦收到请求,服务器(向客户端)发回一个状态行,比如”HTTP/1.1 200 OK”,和(响应的)消息,消息的消息体可能是请求的文件、错误消息、或者其它一些信息。

soap 协议:它描述了一种在分散或分布式的环境中如何交换信息的轻量级协议。soap在http协议的基础上,一个基于XML的协议。

不同:都是底层的通信协议,请求包的格式不同而已,soap包是XML格式,http纯文本格式。

关系:SOAP是个通信协议, SOAP在HTTP协议的基础上,把编写成XML的REQUEST参数, 放在HTTP BODY上提交个WEB SERVICE服务器(SERVLET,ASP什么的) 处理完成后,结果也写成XML作为RESPONSE送回用户端, 为了使用户端和WEB SERVICE可以相互对应,可以使用WSDL作为这种通信方式的描述文件,利用WSDL工具可以自动生成WS和用户端的框架文件,SOAP具备把复杂对象序列化捆绑到XML里去的能力。

Web Service

1、它是基于SOAP协议的,数据格式是XML

2、只支持HTTP协议

3、它不是开源的,但可以被任意一个了解XML的人使用

4、它只能部署在IIS上

WCF

1、这个也是基于SOAP的,数据格式是XML

2、这个是Web Service(ASMX)的进化版,可以支持各种各样的协议,像TCP,HTTP,HTTPS,Named Pipes, MSMQ.

3、WCF的主要问题是,它配置起来特别的繁琐

4、它不是开源的,但可以被任意一个了解XML的人使用

5、它可以部署应用程序中或者IIS上或者Windows服务中

Web API

1、这是一个简单的构建HTTP服务的新框架

2、在.net平台上Web API 是一个开源的、理想的、构建REST-ful 服务的技术

3、不像WCF REST Service.它可以使用HTTP的全部特点(比如URIs、request/response头,缓存,版本控制,多种内容格式)

4、它也支持MVC的特征,像路由、控制器、action、filter、模型绑定、控制反转(IOC)或依赖注入(DI),单元测试。这些可以使程序更简单、更健壮

5、它可以部署在应用程序和IIS上

6、这是一个轻量级的框架,并且对限制带宽的设备,比如智能手机等支持的很好

7、Response可以被Web API的MediaTypeFormatter转换成Json、XML 或者任何你想转换的格式。

技术这么多,我该选谁?

1、当你想创建一个支持消息、消息队列、双工通信的服务时,你应该选择WCF

2、当你想创建一个服务,可以用更快速的传输通道时,像TCP、NamedPipes或者甚至是UDP(在WCF4.5中),在其他传输通道不可用的时候也可以支持HTTP。

3、当你想创建一个基于HTTP的面向资源的服务并且可以使用HTTP的全部特征时(比如URIs、request/response头,缓存,版本控制,多种内容格式),你应该选择WebAPI

4、当你想让你的服务用于浏览器、手机、iPhone和平板电脑时,你应该选择Web API

来自 <https://www.cnblogs.com/bolang100/p/10642419.html>

65、前后端分离

首先什么是前后端分离?

最核心的就是无论你后端换了什么语言,换了什么人去编写,换了什么样的服务器,只要你们定义的一个接口规则不变,然后不会影响到用户的使用,数据的一个展示。

同时反过来也一样,无论你前端换了什么UI框架,欸,我今天用easyui,明天我用layui,后天我用bootstrap,你也能够根据定义的接口文档去展示相关数据和效果,那么就是前后端分离。

说白了就是相互之间是独立的,这就是为什么有前后端分离这个观点出来,并且大家都认可不迟反对态度,恰恰就是说明前后端分离当中的两个字,“分离”

66、{ get; set; }写法

代表,属性xxx 可以 是获取或设置。
如果是 仅是 set 则只能设置,反之亦然。
老版本的.net framework 对于属性,不能省略,必须这样做:

1
2
3
4
5
6
int adminID = 0;
public AdminID
{
get{return adminID;}
set{adminID=value;}
}

而现在的版本可以省略,仅仅需要:
public AdminID{get;set;} 其代表的意义是一样的,就是定义类 Admin 的属性 AdminID

  • Post title:C# dotnet的基础面试题
  • Post author:Yuxuan Wu
  • Create time:2021-03-18 16:02:11
  • Post link:yuxuanwu17.github.io2021/03/18/2021-03-19-Csharp-dotnet-的基础面试题/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.