.Net部分 面试问题

发布时间:2016-12-7 18:31:08 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了".Net部分 面试问题",主要涉及到.Net部分 面试问题方面的内容,对于.Net部分 面试问题感兴趣的同学可以参考一下。

计算机面试问题 2008年07月14日 星期一 上午 10:49 一、ADO 与ADO.NET两种数据访问方式区别? 1. ADO与ADO.NET简介   ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用、高速度、低内存支出和占用磁盘空间较少,支持用于建立基于客户端/服务器和 Web 的应用程序的主要功能。但是ADO使用OLE DB接口并基于微软的COM技术,而ADO.NET拥有自己的ADO.NET接口并且基于微软的.NET体系架构。众所周知.NET体系不同于COM体系,ADO.NET接口也就完全不同于ADO和OLE DB接口,这也就是说 ADO.NET和ADO是两种数据访问方式。      2. 数据访问方式的历史   下面简单的回顾一下微软的数据访问方式所走过的几个阶段。      ODBC – (Open Database Connectivity)是第一个使用SQL访问不同关系数据库的数据访问技术。使用ODBC应用程序能够通过单一的命令操纵不同的数据库,而开发人员需要做的仅仅只是针对不同的应用加入相应的ODBC驱动。      DAO - (Data Access Objects)不像ODBC那样是面向C/C++程序员的,它是微软提供给Visual Basic开发人员的一种简单的数据访问方法,用于操纵Access数据库。      RDO – 在使用DAO访问不同的关系型数据库的时候,Jet引擎不得不在DAO和ODBC之间进行命令的转化,导致了性能的下降,而RDO(Remote Data Objects)的出现就顺理成章了。      OLE DB – 随着越来越多的数据以非关系型格式存储,需要一种新的架构来提供这种应用和数据源之间的无缝连接,基于COM(Component Object Model)的OLE DB应运而生了。      ADO – 基于OLE DB之上的ADO更简单、更高级、更适合Visual Basic程序员,同时消除了OLE DB的多种弊端,取而代之是微软技术发展的趋势。         ADO架构图表      3. ADO与ADO.NET对照   在开始设计.NET体系架构时,微软就决定重新设计数据访问模型,以便能够完全的基于XML和离线计算模型。两者的区别主要有:      ADO以Recordset存储,而ADO.NET则以DataSet表示。Recordset看起来更像单表,如果让Recordset以多表的方式表示就必须在SQL中进行多表连接。反之,DataSet可以是多个表的集合。ADO 的运作是一种在线方式,这意味着不论是浏览或更新数据都必须是实时的。ADO.NET则使用离线方式,在访问数据的时候ADO.NET会利用XML制作数据的一份幅本,ADO.NET的数据库连接也只有在这段时间需要在线。      由于ADO使用COM技术,这就要求所使用的数据类型必须符合COM规范,而ADO.NET基于XML格式,数据类型更为丰富并且不需要再做COM编排导致的数据类型转换,从而提高了整体性能。           4. 小结   ADO.NET为.NET构架提供了优化的数据访问模型,和基于COM的ADO是完全两样的数据访问方式。 二、DataSet与DataReader的区别 ADO.NET 提供以下两个对象,用于检索关系数据并将其存储在内存中:DataSet和DataReader。DataSet提供一个内存中数据的关系表示形式,一整套包括一些表在内的数据(这些表包含数据、对数据进行排序并约束数据),以及表之间的关系。DataReader提供一个来自数据库的快速、仅向前、只读数据流。  当使用DataSet时,经常会利用DataAdapter(也可能是CommandBuilder)与数据源进行交互。当使用 DataSet时,也可以利用DataView对DataSet中的数据应用排序和筛选。也可以从DataSet继承,创建强类型DataSet,用于将表、行和列作为强类型对象属性公开。  下列主题包括的信息涉及:使用DataSet或DataReader的最佳时机、如何优化访问它们所包含数据、以及如何优化使用DataAdapter(包括CommandBuilder)和DataView的技巧。  DataSet与DataReader  当设计应用程序时,要考虑应用程序所需功能的等级,以确定使用DataSet或者是DataReader。  要通过应用程序执行以下操作,就要使用DataSet:  r 在结果的多个离散表之间进行导航。  r 操作来自多个数据源(例如,来自多个数据库、一个XML文件和一个电子表格的混合数据)的数据。  r 在各层之间交换数据或使用XML Web服务。与DataReader不同的是,DataSet能传递给远程客户端。  r 重用同样的记录集合,以便通过缓存获得性能改善(例如排序、搜索或筛选数据)。  r 每条记录都需要执行大量处理。对使用DataReader返回的每一行进行扩展处理会延长服务于DataReader的连接的必要时间,这影响了性能。  r 使用XML操作对数据进行操作,例如可扩展样式表语言转换(XSLT转换)或XPath查询。  对于下列情况,要在应用程序中使用DataReader:  r 不需要缓存数据。  r 要处理的结果集太大,内存中放不下。  r 一旦需要以仅向前、只读方式快速访问数据。  注填充DataSet时,DataAdapter使用DataReader。因此,使用DataAdapter取代DataSet提升的性能表现为节省了 DataSet占用内存和填充DataSet需要的循环。一般来说,此性能提升只是象征性的,因此,设计决策应以所需功能为基础。 三、基本概念 1、面向对象的语言具有封装性、继承性、多态性。 2、ADO.NET中的五个主要对象Connection、Command、DataSet、DataReader、DataAdapter 3、ASP.NET中的身份验证有Windows、Forms、Passport,一般采用Forms,比较简单、适用面广 4、接口----接口定义了一组方法(Method,子程序或函数例程[译注:指Visual Basic .NET中的Sub和Function])、属性(Property)、事件(Event)和域(Field,变量或特性),这些都被声明为公有。接口也可以被另一个接口继承。任何继承了一个接口的类或结构都必须实现接口继承链中所有接口所定义的成员。 5、继承------继承是指一个类——称为子类[译注:亦称派生类],可以基于另一个类——称为基类[译注:亦称父类、超类]。继承提供了一种建立对象层次的机制。继承使得你能够在你自己的类中使用另外一个类的接口和代码。 base->访问基类的成员。 this->引用调用一个方法的当前对象。 6、抽象类-------抽象类是一种特殊的基类。除了通常的类成员,它们还带有抽象类成员。抽象类成员是指没有实现而只有声明的方法和属性。所有直接从抽象类派生的类都必须实现所有这些抽象方法和属性。 抽象方法不能实例化。这样做[译注:指实例化一个抽象类]是不合逻辑的,因为那些抽象成员没有实现。那么,不能实例化一个类有什么好处呢?很多!抽象类稳坐类继承树的顶端。它们确定了类的结构和代码的意图。用它们可以得到更易搭建的框架。这是可能的,因为抽象类具有这个框架中所有基类的一般信息和行为。 7、接口和抽象类之间的区别--------接口和抽象类关系很紧密,它们都具有对成员的抽象。 对于一个抽象类,至少一个方法是抽象方法既可,这意味着它也可以具有具体方法[译注:Concrete Method,这只是相对于抽象方法而言,面向对象中并没有这个概念]。 对于一个接口,所有的方法必须都是抽象的。 实现了一个接口的类必须为接口中的所有方法提供具体的实现,否则只能声明为抽象类。 在C#中,多重继承(Multiple Inheritance)只能通过实现多个接口得到。抽象类只能单继承[译注:C#中的单继承是指所有类作为基类的时候都只能是派生类声明中唯一的基类,而不仅仅是抽象类]。 接口定义的是一个契约,其中只能包含四种实体,即方法、属性、事件和索引器。因此接口不能包含常数(Constant)、域、操作符、构造器、析构器、静态构造器或类型[译注:指嵌套的类型]。 同时,一个接口还不能包含任何类型的静态成员。修饰符abstract、public、protected、internal、private、virtual、override都是不允许出现的,因为它们在这种环境中是没有意义的。 类中实现的接口成员必须具有公有的可访问性。 8、多态性--------多态性反映了能够在多于一个类的对象中完成同一事物的能力——用同一种方法在不同的类中处理不同的对象。例如,如果Customer和Vendor对象都有一个Name属性,则我们可以写一个事物来调用Name属性而不管我们所使用的是Customer对象还是Vendor对象,这就是多态性。 交通工具是多态性的一个很好的例子。一个交通工具接口可以只包括所有交通工具都具有的属性和方法,还可能包括颜色、车门数、变速器和点火器等。这些属性可以用于所有类型的交通工具,包括轿车、卡车和挂车。 多态性不在交通工具的属性和方法背后实现代码。相反,多态性只是实现接口。如果轿车、卡车和挂车都实现了同样的交通工具接口,则所有这三个类的客户代码是完全一样的。 C#通过继承来为我们提供多态性。C#提供了virtual关键字用于定义一个支持多态的方法。 9、结构----------结构是和类相似的一种封装构造,因为它可以包含数据、类型和函数成员。但和类不同的 是,结构是值类型,因此存放在内存中称为栈的地方。结构通常用来存入简单数据类型-- 在内存中有固定大小的实体----的集合,事实上,内建的基本值类型Int32、Int64、Double 等在.NET Framework中实现为结构。 10、委托---------委托是提供对具有特定返回类型和参数列表的方法的一般引用的引用类型。它的本质上和C或C++中的函数指针相似。但和C++函数指针不同的是,委托是完全面向对象的---它们既封装方法又封装对象实例。委托是用户定义的类型,所以当定义委托时,实际上是定义一个特定类型的委托,而不是一个 具体的实例 11、.Net中的内存回收机制  垃圾回收器是用来管理应用程序的内存分配和释放的。在垃圾回收器出现以前,程序员在使用内存时需要向系统申请内存空间。有些语言,例如Visual Basic,可以自动完成向系统申请内存空间的工作。但是在诸如Visual C ++的语言中要求程序员在程序代码中申请内存空间。如果程序员在使用了内存之后忘了释放内存,则会引起内存泄漏。但是有了垃圾回收器,程序员就不必关心内存中对象在离开生存期后是否被释放的问题。当一个应用程序在运行的时候,垃圾回收器设置了一个托管堆。托管堆和C语言中的堆向类似,但是程序员不需要从托管堆中释放对象,并且在托管堆中对象的存放是连续的。   每次当开发人员使用 new 运算符创建对象时,运行库都从托管堆为该对象分配内存。新创建的对象被放在上次创建的对象之后。垃圾回收器保存了一个指针,该指针总是指向托管堆中最后一个对象之后的内存空间。当新的对象被产生时,运行库就知道应该将新的对象放在内存的什么地方。同时开发人员应该将相同类型的对象放在一起。例如当开发人员希望向数据库写入数据的时侯,首先需要创建一个连接对象,然后是Command对象,最后是DataSet对象。如果这些对象放在托管堆相邻的区域内,存取它们就非常快。 四、Public、Protected、Internal、Protected internal、Private的访问权限 1、Public ------公共成员,成员对于任何人都是可见的。我们可以在类内部的和类的子孙的代码中通过使用类的实例来访问一个公有的成员。 2、Protected------保护成员,成员和私有成员类似,只能由包含它的类访问。然而,受保护成员可以由一个类的子类所使用。如果类中的一个成员可能被该类的子类访问,它应该声明未受保护的 3、 Internal/Friend--------成员对整个应用程序是公有的,但对于其他的外部应用程序是私有的。当我们希望其他应用程序能够使用当前应用程序中的包含的一个类,但又希望这个类为当前应用程序保留一定的功能时,就要用到内部/友元成员。在C#中我们使用internal,而在 Visual Basic .NET中我们使用Friend。 4、Protected internal -------包括了 Protected和Internal修饰符,成员只能由包含了基类的应用程序中的从该基类派生的子类所访问。当你希望一个类中的成员只能由其子类访问,并且拒绝其他应用程序访问该类的这个成员的时候,你就要将其声明未受保护内部成员。 5、Private -------私有成员,成员是隐藏的,只有对类本身是可用的。所有使用了一个类的实例的代码都不能直接访问一个私有成员,这个类的子类也不允许。 五、ASP.NET两个页面之间传递值的几种方式 ASP.NET 提供了卓越的事件驱动编程模型,让开发者简化了应用程序的总体设计,但是这个也造成了它固有的一些问题,例如,使用传统的ASP里,我们可以通过使用 POST方法很容易地实现页面间传递值,同样的事情,在使用事件驱动编程模型的ASP.NET就不是那么容易了,当然了,我们仍然有一些方法可以实现同样的功能。本文将试着使用不同的可能的方法来解决这个问题,但可以预见是,本文将包含使用querystring,session变量以及 server.Transfer方法来实现页面间的值传递。 使用QueryString 使用QuerySting在页面间传递值已经是一种很老的机制了,这种方法的主要优点是实现起来非常简单,然而它的缺点是传递的值是会显示在浏览器的地址栏上的(不安全),同时又不能传递对象,但是在传递的值少而安全性要求不高的情况下,这个方法还是一个不错的方案。使用这种方法的步骤如下: 1,使用控件创建web表单(form) 2,创建可以返回表单的按钮和链接按钮 3,在按钮或链接按钮的单击事件里创建一个保存URL的字符变量 4,在保存的URL里添加QueryString参数 5,使用Response.Redirect重定向到上面保存的URL 下面的代码片断演示了如何实现这个方法: 源页面代码: private void Button1_Click (object sender, System.EventArgs e) { string url; url="anotherwebform.aspx?name=" + TextBox1.Text + "&email=" + TextBox2.Text; Response.Redirect(url); } 目标页面代码: private void Page_Load (object sender, System.EventArgs e) { Label1.Text=Request.QueryString["name"]; Label2.Text=Request.QueryString["email"]; } 使用Session变量 使用Session变量是可以在页面间传递值的的另一种方式,在本例中我们把控件中的值存在Session变量中,然后在另一个页面中使用它,以不同页面间实现值传递的目的。但是,需要注意的是在Session变量存储过多的数据会消耗比较多的服务器资源,在使用session时应该慎重,当然了,我们也应该使用一些清理动作来去除一些不需要的session来降低资源的无谓消耗。使用Session变量传递值的一般步骤如下: 1,在页面里添加必要的控件 2,创建可以返回表单的按钮和链接按钮 3,在按钮或链接按钮的单击事件里,把控件的值添加到session变量里 4,使用Response.Redirect方法重定向到另一个页面 5,在另一个页面提取session的值,在确定不需要使用该session时,要显式清除它 下面的代码片断演示了如何实现这个方法: 源页面代码: private void Button1_Click (object sender, System.EventArgs e) { //textbox1 and textbox2 are webform //controls Session["name"]=TextBox1.Text; Session["email"]=TextBox2.Text; Server.Transfer("anotherwebform.aspx"; } 目标页面代码: private void Page_Load (object sender, System.EventArgs e) { Label1.Text=Session["name"].ToString(); Label2.Text=Session["email"].ToString(); Session.Remove("name"; Session.Remove("email"; } 使用Server.Transfer 这个方法相比上面介绍的方法稍微复杂一点,但在页面间值传递中却是特别有用的,使用该方法你可以在另一个页面以对象属性的方式来存取显露的值,当然了,使用这种方法,你需要额外写一些代码以创建一些属性以便可以在另一个页面访问它,但是,这个方式带来的好处也是显而易见的。总体来说,使用这种方法是简洁的同时又是面向对象的。使用这种方法的整个过程如下: 1,在页面里添加必要的控件 2,创建返回值的Get属性过程 3,创建可以返回表单的按钮和链接按钮 4,在按钮单击事件处理程序中调用Server.Transfer方法转移到指定的页面 5,在第二个页面中,我们就可以使用Context.Handler属性来获得前一个页面实例对象的引用,通过它,就可以使用存取前一个页面的控件的值了 以下代码综合实现上述步骤过程的代码: 源页面代码: 把以下的代码添加到页面中 public string Name { get { return TextBox1.Text; } } public string EMail { get { return TextBox2.Text; } } 然后调用Server.Transfer方法 private void Button1_Click (object sender, System.EventArgs e) { Server.Transfer("anotherwebform.aspx"; } 目标页面代码: private void Page_Load (object sender, System.EventArgs e) { //create instance of source web