美文网首页面试
.NET 面试题汇总(二)

.NET 面试题汇总(二)

作者: 寒剑飘零 | 来源:发表于2017-02-27 20:51 被阅读204次

    目录
    本次给大家介绍的是我收集以及自己个人保存一些.NET面试题第二篇
    简介1.接口
    2.您在什么情况下会用到虚方法或抽象类,接口?
    3.重载(Overload )和覆写(Override)的区别
    4.值类型和引用类型的区别?写出C#的样例代码。
    5.委托和事件简述
    6.Session,ViewState,Application,cookie的区别?
    7.Application,Session,Cookie,ViewState和Cache生命周期
    8.ajax原理
    9.请叙述属性与索引器的区别
    10.String类与StringBuilder类有什么区别?为啥在.Net类库中要同时存在这2个类?
    11.浅谈C#中的枚举
    12.C#的New关键字的几种用法

    回到顶部
    简介
    此次包含的不止是.NET知识,也包含少许前端知识以及.net面试时所涉及的种种考点,希望能给找工作的同学们哪怕一点点帮助。

    在此提醒下,本文适合:
    刚毕业的萌新
    工作不久换工作的
    大牛可忽略啦

    1.接口
    文章引用:http://www.cnblogs.com/jiajiayuan/archive/2011/09/16/2178462.html
    ①.接口的特性:
    接口类似于抽象基类,不能直接实例化接口;接口中的方法都是抽象方法,实现接口的任何非抽象类型都必须实现接口的所有成员:

    当显式实现该接口的成员时,实现的成员不能通过类实例访问,只能通过接口实例访问。
    当隐式实现该接口的成员时,实现的成员可以通过类实例访问,也可以通过接口实例访问,但是实现的成员必须是公有的。

    接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型、不能包含静态成员。
    接口成员是自动公开的,且不能包含任何访问修饰符。
    接口自身可从多个接口继承,类和结构可继承多个接口,但接口不能继承类。

    ②为什么不能指定接口中方法的修饰符?
    接口中的方法用来定义对象之间通信的契约,指定接口中的方法为私有或保护没有意义。它们默认为公有方法。

    interface IProgram { void Fun(); } class Program:IProgram { //显式实现接口成员 void IProgram.Fun() { Console.WriteLine("I am Fun."); } staticvoid Main(string[] args) { IProgram p =new Program(); //声明一个接口实例,但不是对接口进行实例化 p.Fun(); Console.Read(); } }

    ③实现接口可以显式实现和隐式实现,那么这两种实现到底有什么优缺点呢?
    一般情况,当类或者结构要实现的是单个接口,可以使用隐式实现。如果类或者结构继承了多个接口且接口中具有相同名称成员时,就要用到显式实现,当显式实现方式存在时,隐式实现方式就失效了。

    interface IProgram { void Fun(); } interface IAProgram { void Fun(); } class Program : IProgram, IAProgram { void IProgram.Fun() //显式实现接口IProgram { Console.WriteLine("I am IProgram Fun."); } void IAProgram.Fun() //显式实现接口IAProgram { Console.WriteLine("I am IAProgram Fun."); } //public void Fun() //隐式实现接口 //{ // Console.WriteLine("I am Program Fun."); //} staticvoid Main(string[] args) { //IProgram p = new Program(); //p.Fun(); //IAProgram ap = new Program(); //ap.Fun(); Program pro =new Program(); ((IProgram)pro).Fun(); ((IAProgram)pro).Fun(); Console.Read(); } }

    ④接口的继承:
    接口继承和类继承不同
    首先,类继承不仅是说明继承,而且也是实现继承;而接口继承只是说明继承。也就是说,派生类可以继承基类的方法实现,而派生的接口只继承了父接口的成员方法说明,而没有继承父接口的实现;
    其次,C#中类继承只允许单继承,但是接口继承允许多继承,一个子接口可以有多个父接口。接口可以从零或多个接口中继承。从多个接口中继承时,用":"后跟被继承的接口名字,多个接口名之间用","分割。被继承的接口应该是可以访问得到的,比如从private 类型或internal 类型的接口中继承就是不允许的。接口不允许直接或间接地从自身继承。和类的继承相似,接口的继承也形成接口之间的层次结构。

    interface IProgram { void Fun(); } interface IAProgram:IProgram { } class Program : IAProgram { void IProgram.Fun() { Console.WriteLine("I am IProgram Fun."); } static void Main(string[] args) { Program pro =new Program(); ((IAProgram)pro).Fun(); Console.Read(); } }

    ⑤接口的覆盖:
    由于接口的实现没有方法体,抽象方法也没有方法体,那么当我们在接口的实现方法里调用抽象方法时,会如何执行呢?

    interface IProgram { void Fun(); } abstract class AProgram : IProgram { public abstract void AFun(); void IProgram.Fun() { AFun(); } } class Program:AProgram { public override void AFun() { Console.WriteLine("I am AProgram."); } static void Main(string[] args) { IProgram pro =new Program(); pro.Fun(); Console.Read(); } }//结果:I am Aprogram.

    通过断点,可以看到,当执行pro.Fun();时,首先会跳到接口的实现方法里,然后去调用抽象函数的实现方法,当抽象函数的方法实现后,再回到接口的实现方法,直到执行完成
    当我们在实现接口的方法里调用虚函数呢?

    interface IProgram { void Fun(); } class AProgram : IProgram { public virtual void AFun() //注意这里是虚函数 { Console.WriteLine("I am virtual AFun."); } void IProgram.Fun() { AFun(); } } class Program:AProgram { public override void AFun() //这里是Override重写 { Console.WriteLine("I am override AFun."); } static void Main(string[] args) { IProgram pro =new Program(); pro.Fun(); Console.Read(); } }

    这时,我们发现,执行的顺序和上一个例子是相同的。所以结果为:I am override AFun.由此,我们可以继续联想,当我们把override关键字,换成new呢?是不是也是同样的结果,还是和我们以前讲的例子一样,是隐藏呢?

    我们把上面的例子进行改进:
    interface IProgram { void Fun(); } class AProgram : IProgram { public virtual void AFun() { Console.WriteLine("I am virtual AFun."); } void IProgram.Fun() { AFun(); } } class Program:AProgram { public new void AFun() { Console.WriteLine("I am new AFun."); } static void Main(string[] args) { Program pro =new Program(); ((IProgram)pro).Fun(); pro.AFun(); Console.Read(); } }

    结果为:

    I am virtual AFun.I am new AFun.
    由于前面已经讲过了==,这里不在对此进行分析,由此我们可知使用New关键字是对其进行隐藏,当对接口实现的方法里调用的是虚方法时,和类的执行过程是一样的。
    ⑥接口和抽象类的区别
    接口用于规范,抽象类用于共性。
    接口中只能声明方法,属性,事件,索引器。而抽象类中可以有方法的实现,也可以定义非静态的类变量。
    抽象类是类,所以只能被单继承,但是接口却可以一次实现多个。
    抽象类可以提供某些方法的部分实现,接口不可以。
    抽象类的实例是它的子类给出的。接口的实例是实现接口的类给出的。
    在抽象类中加入一个方法,那么它的子类就同时有了这个方法。而在接口中加入新的方法,那么实现它的类就要重新编写(这就是为什么说接口是一个类的规范了)。
    接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。
    此外接口不能包含字段、构造函数、析构函数、静态成员或常量。

    ⑦C#中的接口和类有什么异同

    不能直接实例化接口。
    接口不包含方法的实现。
    接口可以实现多继承,而类只能是单继承。
    类定义可在不同的源文件之间进行拆分。


    接口、类和结构可从多个接口继承。
    接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
    接口可以包含事件、索引器、方法和属性。
    一个类可以实现多个接口。

    2.您在什么情况下会用到虚方法或抽象类,接口?
    如果某个方法可能性在派生类中会被重写。这时就将该方法写为虚方法。
    抽象类:是一个类型,与派生类之间的关系是一个“ISA”的关系。用来做基类,抽象类不能创建对象,类中包括抽象方法和实例方法。
    接口:是设计一个规范,描述了Can do ;与实现类之间是中”LINE A 的关系,C#中接口不能包含字段访问修饰符。

    3.重载(Overload )和覆写(Override)的区别
    简述:简单的说,一个是同一个函数的几种形式,一个是重写父类函数。
    重载:当类包含两个名称相同但签名不同(方法名相同,参数列表不相同)的方法时发生方法重载。用方法重载来提供在语义上完成相同而功能不同的方法。

    覆写:在类的继承中使用,通过覆写子类方法可以改变父类虚方法的实现。

    区别:
    方法的覆盖是子类和父类之间的关系,是垂直关系;方法的重载是同一个类中方法之间的关系,是水平关系。
    覆盖只能由一个方法,或只能由一对方法产生关系;方法的重载是多个方法之间的关系。
    覆盖要求参数列表相同;重载要求参数列表不同。
    覆盖关系中,调用那个方法体,是根据对象的类型(对象对应存储空间类型)来决定;重载关系,是根据调用时的实参表与形参表来选择方法体的。

    4.值类型和引用类型的区别?写出C#的样例代码。
    简述:值类型包括简单类型、结构体类型和枚举类型,引用类型包括自定义类、数组、接口、委托等
    赋值方式:将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对象的引用,而不复制对象本身。
    派生:值类型不可能派生出新的类型,所有的值类型均隐式派生自 System.ValueType。但与引用类型相同的是,结构也可以实现接口。
    null:与引用类型不同,值类型不可能包含 null 值。然而,可空类型功能允许将 null 赋给值类型。
    每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。值类型主要由两类组成:结构、枚举
    ①. 结构分为以下几类:Numeric(数值)类型、整型、浮点型、decimal、bool、用户定义的结构。
    ②. 引用类型的变量又称为对象,可存储对实际数据的引用。声明引用类型的关键字:class、interface、delegate、内置引用类型: object、string

    值类型存贮在中,而引用类型存贮在动态的堆中,栈是先进先出的有系统管理的空间,而堆是由应用程序控制的可随时申请和释放该空间,在Donnet中一般情况下有垃圾收集器处理,他们的不同导致在编程上的不同。例:

    using System;using System.Text;class EventDel{ static void Main(string[] args) { StringBuilder a=new StringBuilder();//将StringBuilder的一个首地址传给a StringBuilder b=a; //将StringBuilder的一个首地址传给b b.Append("mxh"); Console.WriteLine(a); a=null; Console.WriteLine(b); }}

    "a=null"的意思是:a的引用置为空但此时StringBuilder的堆空间并没有被释放,因此在此之后,输出b时,仍然可以输出mxh

    输出结果:mxhmxh
    5.委托和事件简述
    参考资料 :C# 知识回顾 - 委托 delegate
    C# 知识回顾 - 委托 delegate (续)
    事件是不是一种委托?
    委托是一种安全的函数指针,事件是一种消息机制
    委托与事件是什么关系?为什么要使用委托
    委托提供了封装方法的方式,事件是某动作已发生的说明,事件是建立于委托之上的。
    程序运行时同一个委托能够用来调用不同的方法,只要改变它的引用方法即可,因此委托调节器用的方法不是在编译时决定的,而是在运行时确定的.
    6.Session,ViewState,Application,cookie的区别?
    Session:用于保持状态的基于 Web 服务器的方法。Session 允许通过将对象存储在Web 服务器的内存中在整个用户会话过程中保持任何对象。主要用于保持代码隐藏类中对象的状态。为每个用户创建的,用于存储单个用户,因为他是相对每个用户的.所以可能来取得在线人数等。
    ViewState:主要用于保持 Web 页上控件的状态。当 Web 页上的控件被绑定到代码隐藏类中的对象。
    Application 用于存储所有用户都可视的信息.所以它存储的是要让所有用户共享的一些信息.如总访问数等Cache,页面缓存。
    Cookie:通常我们都把它放在客户端,也可以存储在服务器端。主要用它存储用户的个性设制,和登陆信息。

    7.Application,Session,Cookie,ViewState和Cache生命周期
    在ASP.NET中,有很多种保存信息的内置对象,如:Application,Session,Cookie,ViewState和Cache等。下面分别介绍它们的用法和区别。

    ①.Application对象
    Application用于保存所有用户的公共的数据信息,如果使用Application对象,一个需要考虑的问题是任何写操作都要在Application_OnStart事件(global.asax)中完成.尽管使用Application.Lock和Applicaiton.Unlock方法来避免写操作的同步,但是它串行化了对Application对象的请求,当网站访问量大的时候会产生严重的性能瓶颈.因此最好不要用此对象保存大的数据集合. 下面我们做个在线用户统计的例子来说明这个问题:

    Global.asax类 代码using System;using System.Collections;using System.ComponentModel;using System.Web;using System.Web.SessionState;using System.IO; /// Global 的摘要说明。 public class Global : System.Web.HttpApplication { /// 必需的设计器变量。 private System.ComponentModel.IContainer components = null; private FileStream fileStream; private StreamReader reader;//读字符流 private StreamWriter writer;//写字符流 public Global() { InitializeComponent(); } protected void Application_Start(Object sender, EventArgs e) { Application["CurrentGuests"]=0;//初始花为0; fileStream = File.Open(Server.MapPath("counts.text"),FileMode.OpenOrCreate);//文件不存在,创建文件 reader = new StreamReader(fileStream);//要读取的完整路径 Application["AllGuests"] = Convert.ToInt32(reader.ReadLine()); //从当前流中读取一行字符并将数据作为字符串返回 reader.Close();//关闭流 } protected void Session_Start(Object sender, EventArgs e)//当用户访问网站时,在线用户+1,总访问数+1 { Application.Lock();//同步,避免同时写入 Application["CurrentGuests"] =(int)Application["CurrentGuests"]+ 1;//总在线用户数 Application["AllGuests"] =(int)Application["AllGuests"]+ 1;//访问网站的总用户数 fileStream = new FileStream(Server.MapPath("counts.text"),FileMode.OpenOrCreate,FileAccess.ReadWrite);// writer = new StreamWriter(fileStream);//实现一个写入流,使其以一种特定的编码向流中写入字符 writer.WriteLine(Application["AllGuests"].ToString());//把访问网站的总用户数再次写入到文件 writer.Close();//关闭写入流 Application.UnLock();//同步结束 } protected void Session_End(Object sender, EventArgs e)//当前用户退出网站时,在线用户数量-1, { Application.Lock(); Application["CurrentGuests"] =(int)Application["CurrentGuests"] - 1;//总在线用户数量-1 Application.UnLock(); } (2) WebForm1.aspx private void Page_Load(object sender, System.EventArgs e) { this.Label1.Text = "正在访问站点的用户数:" + Application["CurrentGuests"].ToString(); this.Label2.Text ="访问过站点的总用户数:" + Application["AllGuests"].ToString(); }

    ②.Session对象
    Session用于保存每个用户的专用信息.每个客户端用户访问时,服务器都为每个用户分配一个唯一的会话ID(Session ID) . 她的生存期是用户持续请求时间再加上一段时间(一般是20分钟左右).Session中的信息保存在Web服务器内容中,保存的数据量可大可小.当Session超时或被关闭时将自动释放保存的数据信息.由于用户停止使用应用程序后它仍然在内存中保持一段时间,因此使用Session对象使保存用户数据的方法效率很低.对于小量的数据,使用Session对象保存还是一个不错的选择.使用Session对象保存信息的代码如下:

    //存放信息Session["key"]="value"//读取数据string UserName=Session["key"].ToString();

    ③.Cookie对象
    Cookie用于保存客户浏览器请求服务器页面的请求信息,程序员也可以用它存放非敏感性的用户信息,信息保存的时间可以根据需要设置.如果没有设置Cookie失效日期,它们仅保存到关闭浏览器程序为止.如果将Cookie对象的Expires属性设置为Minvalue,则表示Cookie永远不会过期.Cookie存储的数据量很受限制,大多数浏览器支持最大容量为4K,因此不要用来保存数据集及其他大量数据.由于并非所有的浏览器都支持Cookie,并且数据信息是以明文文本的形式保存在客户端的计算机中,因此最好不要保存敏感的,未加密的数据,否则会影响网站的安全性.使用Cookie对象保存的代码如下:

    //存放信息Response.Cookies["key"].Value="value";//读取信息string UserID=Response.Cookies["key"].Value;

    ④.ViewState对象
    ViewState 常用于保存单个用户的状态信息,有效期等于页面的生存期。跟隐藏控件相似。viewstate是在本页面之内各函数间进行传值的 , 至于为什么要使用这种方法是因为在一个事件发生之后 , 页面可能会刷新 , 如果定义全局变量会被清零 , 所以要使用viewstate. ViewState容器可以保持大量的数据,但是必须谨慎使用,因为过多使用会影响应用程序的性能。所有Web服务器控件都使用ViewState在页面回发期音保存自己的状态信息。如果某个控件不需要在回发期间保存状态信息,最好关闭该对象的ViewState,避免不必要的资源浪费。通过给@Page指令添加“EnableViewState=false”属性可以禁止整个页面的ViewState。使用ViewState对象保存信息的代码如下。

    //存放信息 ViewState["key"]="value"; //读取信息 string NameID=ViewState["nameID"].ToString();

    ⑤.Cache对象
    Cache对象用于在HTTP请求间保存页面或数据。该对象的使用可以极大地提高整个应用程序的效率。常用于将频繁访问的大量服务器资源存储在内存中,当用户发出相同的请求后服务器不再次处理而是将Cache中保存的信息返回给用户,节省了服务器处理请求的时间。其生存期依赖于该应用程序的生存期。当重新启动应用程序时,将重新创建其Cache对象的实例。使用Cache对象保存信息的代码如下。

    //存放信息 Cache["nameID"]="0001"; //存放信息 Cache.Insert("nameID","0001"1); //读取信息 string NameID=Cache["nameID"].ToString();

    ⑥.隐藏域
    Hidden控件是属于HTML类型的服务器控件,使用此控件可以实现隐藏域的功能。其实此控件和其它服务器控件的使用没有太大区别,只是它不会在用户端的浏览器中显示,始终处于隐藏状态。但是每次页面提交的时候,此控件和其它服务器控件一同提交到服务器端,因此在服务器端可以使用Value属性获取或保存一些数据信息。使用Hidden控件保存信息的代码如下。

    //存放信息 Hidden.Value="0001"; //获取信息 string NameID=Hidden.Value;

    ⑦.查询字符串
    查询字符串的方式是将要传递的值连接在URL后面,然后通过Response.Redirect方法实现客户端的重定向。这种方式可以实现在两个页面之间传递信息。由于URL的长度有一定的限制,因此不能传递太大的信息,加外安全性也不是很好。传递信息如下。问号后面格式 key1=value1&key2=value2

    Response.Redirect("List.aspx?nameID=0001&gradeID=002"); //执行上面的语句后在IE地址栏显示的URL的代码如下。 http://localhost/List.aspx?nameID=0001&grade=002 //当跳转到List.aspx后,可以通过以下代码获得所传递的信息。 string NameID.GradeID;

    8.ajax原理
    简述: Ajax的原理就是:通过javascript的方式,将前台数据通过xmlhttp对象传递到后台,后台在接收到请求后,将需要的结果,再传回到前台,这样就可以实现不需要页面的回发,页是数据实现来回传递,从页实现无刷新。
    Ajax的原理简单来说,实际上就是通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,我们必须对 XMLHttpRequest有所了解。

    总结:我们可以看出,XMLHttpRequest对象完全用来向服务器发出一个请求的,它的作用也局限于此,但它的作用是整个ajax实现的关键,我们可以把服务器端看成一个数据接口,它返回的是一个纯文本流,当然,这个文本流可以是XML格式,可以是Html,可以是Javascript代码,也可以只是一个字符串。这时候,XMLHttpRequest向服务器端请求这个页面,服务器端将文本的结果写入页面,这和普通的web开发流程是一样的,不同的是,客户端在异步获取这个结果后,不是直接显示在页面,而是先由javascript来处理,然后再显示在页面。
    9.请叙述属性与索引器的区别
    属性
    索引器

    通过名称标识
    通过签名标识

    通过简单名称或成员访问来访问
    通过元素访问来访问

    可以为静态成员或实例成员
    必须为实例成员

    属性的get访问器没有参数
    索引器的get访问器具有与索引器相同的形参表

    属性的set访问器包含隐式value参数器
    除了value参数外,索引的 set 访问器还具有与索引器相同的形参表

    10.String类与StringBuilder类有什么区别?为啥在.Net类库中要同时存在这2个类?
    如果要操作一个不断增长的字符串,尽量不用String类,改用StringBuilder类

    String类原理:String类是一种传统的修改字符串的方式,它确实可以完成把一个字符串添加到另一个字符串上的工作没错,但是在.NET框架下,这个操作实在是划不来。因为系统先是把两个字符串写入内存,接着删除原来的String对象,然后创建一个String对象,并读取内存中的数据赋给该对象。这一来二去的,耗了不少时间。
    StringBulider原理:而使用 System.Text命名空间下面的StringBuilder类就不是这样了,它提供的Append方法,能够在已有对象的原地进行字符串的修改,简单而且直接。
    提醒:一般情况下觉察不到这二者效率的差异,但如果你要对某个字符串进行大量的添加操作,那么StringBuilder类所耗费的时间和 String类简直不是一个数量级的
    11.浅谈C#中的枚举
    枚举类型是一种的值类型,它用于声明一组命名的常数。

    ①.枚举的声明:枚举声明用于声明新的枚举类型。
    访问修辞符 enum 枚举名:基础类型 { 枚举成员 }

    基础类型必须能够表示该枚举中定义的所有枚举数值。枚举声明可以显式地声明 byte、sbyte、short、ushort、int、uint、long 或 ulong 类型作为对应的基础类型。没有显式地声明基础类型的枚举声明意味着所对应的基础类型是 int。

    ②.枚举成员
    枚举成员是该枚举类型的命名常数。任意两个枚举成员不能具有相同的名称。每个枚举成员均具有相关联的常数值。此值的类型就是枚举的基础类型。每个枚举成员的常数值必须在该枚举的基础类型的范围之内。

    public enum TimeofDay:uint { Morning=-3, Afternoon=-2, Evening=-1 }

    产生编译时错误,原因是常数值 -1、-2 和 –3 不在基础整型 uint 的范围内。
    ③.枚举成员默认值
    在枚举类型中声明的第一个枚举成员它的默值为零。以后的枚举成员值是将前一个枚举成员(按照文本顺序)的值加 1 得到的。这样增加后的值必须在该基础类型可表示的值的范围内;否则,会出现编译时错误。

    示例: public enum TimeofDay:uint { Morning, Afternoon, Evening }

    Morning的值为0,Afternoon的值为1,Evening的值为2。
    ④.为枚举成员显示赋值
    允许多个枚举成员有相同的值。没有显示赋值的枚举成员的值,总是前一个枚举成员的值+1

    public enum Number { a=1, b, c=1, d }

    b的值为2,d的值为2.注意:以上枚举值都不能超过它的基础类型范围。否则会报错.
    ⑤.枚举类型与基础类型的转换
    基础类型不能隐式转换为枚举类型; 枚举类型也不能隐式转换为基础类型

    public enum Number { a, b, c, d } class Test { public static void Main() { int i=Number.a;//错误,要强制类型转换(int)Number.a Number n; n=2 //错误,要强制类型转换(Number)2 } }

    ⑥.System.Enum类型
    System.Enum 类型是所有枚举类型的抽象基类,并且从 System.Enum 继承的成员在任何枚举类型中都可用。
    System.Enum 本身不是枚举类型。相反,它是一个类类型,所有枚举类型都是从它派生的。
    System.Enum 从类型 System.ValueType派生

    ⑦.使用枚举类型
    using System; public enum TimeofDay { Morning, Afternoon, Evening } class Test { static void WriteGreeting(TimeofDay timeofDay) { switch(timeofDay) { case TimeofDay.Morning: Console.WriteLine("good morning"); break; case TimeofDay.Afternoon: Console.WriteLine("good afternoon"); break; case TimeofDay.Evening: Console.WriteLine("good evening"); break; } } static void Main() { WriteGreeting(TimeofDay.Morning); WriteGreeting(TimeofDay.Evening); WriteGreeting(TimeofDay.Afternoon); } }

    12.C#的New关键字的几种用法
    ①.new运算符:用于创建对象和调用构造函数。
    用于创建对象和调用构造函数 例:Class_Test MyClass=new Class_Test();
    也用于为值类型调用默认的构造函数

    例:int myInt=new int();

    myInt初始化为0,它是int类型的默认值。该语句的效果等同于:intmyInt=0;
    不能重载new运算符;
    如果new运算符分配内存失败,则它将引发OutOfMemoryException异常。

    ②.new修饰符
    使用new修饰符显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用new修饰符修饰它。

    请看下面的类:
    public class MyClass { public int x; public void Invoke(){} }

    在派生类中用Invoke名称声明成员会隐藏基类中的Invoke方法,即:
    public class MyDerivedC:MyClass { new public void Invoke(){} }

    但是,因为字段x不是通过类似名隐藏的,所以不会影响该字段。
    通过继承隐藏名称采用下列形式之一:
    1.引入类或结构中的常数、指定、属性或类型隐藏具有相同名称的所有基类成员。
    2.引入类或结构中的方法隐藏基类中具有相同名称的属性、字段和类型。同时也隐藏具有相同签名的所有基类方法。
    3.引入类或结构中的索引器将隐藏具有相同名称的所有基类索引器。
    4.在同一成员上同时使用new和override是错误的。
    注意:在不隐藏继承成员的声明中使用new修饰符将生成警告。
    示例:在该例中,嵌套类MyClass隐藏了基类中具有相同名称的类。该例不仅说明了如何使用完全限定名访问隐藏类成员,同时也说明了如何使用new修饰符消除警告消息。

    using System; public class MyBaseC{public class MyClass{public int x=200;public int y;}}public class MyDerivedC:MyBaseC{new public class MyClass //nestedtypehidingthebasetypemembers{public int x=100;public int y;public int z;}public static void Main(){//Creating object from the overlapping class:MyClass S1=new MyClass();//Creating object from the hidden class:MyBaseC.MyClass S2=new MyBaseC.MyClass();Console.WriteLine(S1.x);Console.WriteLine(S2.x);}

    输出:100200
    ③.new约束:用于在泛型声明中约束可能用作类型参数的参数的类型。

    相关文章

      网友评论

        本文标题:.NET 面试题汇总(二)

        本文链接:https://www.haomeiwen.com/subject/vbktgttx.html