本次給大家介紹的是我收集以及自己個人保存一些.NET面試題第二篇
第一篇文章請到這里:【2017年新篇章】 .NET 面試題匯總(一)
簡介
- 此次包含的不止是.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
輸出結果:
mxh
mxh
5.委托和事件簡述
參考資料 :
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);
}
輸出:
100
200