【2017年新篇章】 .NET 面試題匯總(二)


 

正文

本次給大家介紹的是我收集以及自己個人保存一些.NET面試題第二篇

第一篇文章請到這里:【2017年新篇章】 .NET 面試題匯總(一)

簡介

  • 此次包含的不止是.NET知識,也包含少許前端知識以及.net面試時所涉及的種種考點,希望能給找工作的同學們哪怕一點點幫助。

在此提醒下,本文適合:

  • 剛畢業的萌新
  • 工作不久換工作的
  • 大牛可忽略啦

1.接口

文章引用:http://www.cnblogs.com/jiajiayuan/archive/2011/09/16/2178462.html

①.接口的特性:

  1. 接口類似於抽象基類,不能直接實例化接口;接口中的方法都是抽象方法,實現接口的任何非抽象類型都必須實現接口的所有成員:
  • 當顯式實現該接口的成員時,實現的成員不能通過類實例訪問,只能通過接口實例訪問。
  • 當隱式實現該接口的成員時,實現的成員可以通過類實例訪問,也可以通過接口實例訪問,但是實現的成員必須是公有的。
  1. 接口不能包含常量、字段、運算符、實例構造函數、析構函數或類型、不能包含靜態成員。
  2. 接口成員是自動公開的,且不能包含任何訪問修飾符。
  3. 接口自身可從多個接口繼承,類和結構可繼承多個接口,但接口不能繼承類。

②為什么不能指定接口中方法的修飾符?

接口中的方法用來定義對象之間通信的契約,指定接口中的方法為私有或保護沒有意義。它們默認為公有方法。

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

④接口的繼承:

接口繼承和類繼承不同

  1. 首先,類繼承不僅是說明繼承,而且也是實現繼承;而接口繼承只是說明繼承。
    也就是說,派生類可以繼承基類的方法實現,而派生的接口只繼承了父接口的成員方法說明,而沒有繼承父接口的實現;
  2. 其次,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關鍵字是對其進行隱藏,當對接口實現的方法里調用的是虛方法時,和類的執行過程是一樣的。

⑥接口和抽象類的區別

  1. 接口用於規范,抽象類用於共性。
  2. 接口中只能聲明方法,屬性,事件,索引器。而抽象類中可以有方法的實現,也可以定義非靜態的類變量。
  3. 抽象類是類,所以只能被單繼承,但是接口卻可以一次實現多個。
  4. 抽象類可以提供某些方法的部分實現,接口不可以。
  5. 抽象類的實例是它的子類給出的。接口的實例是實現接口的類給出的。
  6. 在抽象類中加入一個方法,那么它的子類就同時有了這個方法。而在接口中加入新的方法,那么實現它的類就要重新編寫(這就是為什么說接口是一個類的規范了)。
  7. 接口成員被定義為公共的,但抽象類的成員也可以是私有的、受保護的、內部的或受保護的內部成員(其中受保護的內部成員只能在應用程序的代碼或派生類中訪問)。
  8. 此外接口不能包含字段、構造函數、析構函數、靜態成員或常量。

⑦C#中的接口和類有什么異同

  1. 不能直接實例化接口。
  2. 接口不包含方法的實現。
  3. 接口可以實現多繼承,而類只能是單繼承。
  4. 類定義可在不同的源文件之間進行拆分。

  1. 接口、類和結構可從多個接口繼承。
  2. 接口類似於抽象基類:繼承接口的任何非抽象類型都必須實現接口的所有成員。
  3. 接口可以包含事件、索引器、方法和屬性。
  4. 一個類可以實現多個接口。

2.您在什么情況下會用到虛方法或抽象類,接口?

  1. 如果某個方法可能性在派生類中會被重寫。這時就將該方法寫為虛方法。
  2. 抽象類:是一個類型,與派生類之間的關系是一個“ISA”的關系。用來做基類,抽象類不能創建對象,類中包括抽象方法和實例方法。
  3. 接口:是設計一個規范,描述了Can do ;與實現類之間是中”LINE A 的關系,C#中接口不能包含字段訪問修飾符。

3.重載(Overload )和覆寫(Override)的區別

簡述:簡單的說,一個是同一個函數的幾種形式,一個是重寫父類函數。

重載:當類包含兩個名稱相同但簽名不同(方法名相同,參數列表不相同)的方法時發生方法重載。用方法重載來提供在語義上完成相同而功能不同的方法。

覆寫:在類的繼承中使用,通過覆寫子類方法可以改變父類虛方法的實現。

區別:

  1. 方法的覆蓋是子類和父類之間的關系,是垂直關系;方法的重載是同一個類中方法之間的關系,是水平關系。
  2. 覆蓋只能由一個方法,或只能由一對方法產生關系;方法的重載是多個方法之間的關系。
  3. 覆蓋要求參數列表相同;重載要求參數列表不同。
  4. 覆蓋關系中,調用那個方法體,是根據對象的類型(對象對應存儲空間類型)來決定;重載關系,是根據調用時的實參表與形參表來選擇方法體的。

4.值類型和引用類型的區別?寫出C#的樣例代碼。

簡述:值類型包括簡單類型、結構體類型和枚舉類型,引用類型包括自定義類、數組、接口、委托等

  1. 賦值方式:將一個值類型變量賦給另一個值類型變量時,將復制包含的值。這與引用類型變量的賦值不同,引用類型變量的賦值只復制對象的引用,而不復制對象本身。
  2. 派生:值類型不可能派生出新的類型,所有的值類型均隱式派生自 System.ValueType。但與引用類型相同的是,結構也可以實現接口。
  3. null:與引用類型不同,值類型不可能包含 null 值。然而,可空類型功能允許將 null 賦給值類型。
  4. 每種值類型均有一個隱式的默認構造函數來初始化該類型的默認值。
    值類型主要由兩類組成:結構、枚舉

    ①. 結構分為以下幾類:Numeric(數值)類型、整型、浮點型、decimal、bool、用戶定義的結構。

    ②. 引用類型的變量又稱為對象,可存儲對實際數據的引用。聲明引用類型的關鍵字:class、interface、delegate、內置引用類型: object、string

  5. 值類型存貯在中,而引用類型存貯在動態的堆中,棧是先進先出的有系統管理的空間,而堆是由應用程序控制的可隨時申請和釋放該空間,在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

輸出結果:
mxh
mxh

5.委托和事件簡述

參考資料 :
C# 知識回顧 - 委托 delegate

C# 知識回顧 - 委托 delegate (續)

事件是不是一種委托?

委托是一種安全的函數指針,事件是一種消息機制

委托與事件是什么關系?為什么要使用委托

委托提供了封裝方法的方式,事件是某動作已發生的說明,事件是建立於委托之上的。

程序運行時同一個委托能夠用來調用不同的方法,只要改變它的引用方法即可,因此委托調節器用的方法不是在編譯時決定的,而是在運行時確定的.

6.Session,ViewState,Application,cookie的區別?

  1. Session:用於保持狀態的基於 Web 服務器的方法。Session 允許通過將對象存儲在Web 服務器的內存中在整個用戶會話過程中保持任何對象。主要用於保持代碼隱藏類中對象的狀態。為每個用戶創建的,用於存儲單個用戶,因為他是相對每個用戶的.所以可能來取得在線人數等。
  2. ViewState:主要用於保持 Web 頁上控件的狀態。當 Web 頁上的控件被綁定到代碼隱藏類中的對象。
  3. Application 用於存儲所有用戶都可視的信息.所以它存儲的是要讓所有用戶共享的一些信息.如總訪問數等Cache,頁面緩存。
  4. 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類型

  1. System.Enum 類型是所有枚舉類型的抽象基類,並且從 System.Enum 繼承的成員在任何枚舉類型中都可用。
  2. System.Enum 本身不是枚舉類型。相反,它是一個類類型,所有枚舉類型都是從它派生的。
  3. 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); }

輸出:
100
200

③.new約束:用於在泛型聲明中約束可能用作類型參數的參數的類型。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM