1、C#中的委託是什麼?事件是不是一種委託?事件和委託的關係。
委託可以把一個方法作爲參數代入另一個方法。
委託可以理解爲指向一個函數的指針。
委託和事件沒有可比性,因爲委託是類型,事件是對象,下面說的是委託的對象(用委託方式實現的事件)和(標準的event方式實現)事件的區別。事件的內部是用委託實現的。因爲對於事件來講,外部只能“註冊自己+=、註銷自己-=”,外界不可以註銷其他的註冊者,外界不可以主動觸發事件,因此如果用Delegate就沒法進行上面的控制,因此誕生了事件這種語法。事件是用來閹割委託實例的,類比用一個自定義類閹割List。事件只能add、remove自己,不能賦值。事件只能+=、-=,不能= 。加分的補充回答:事件內部就是一個private的委託和add、remove兩個方法
面試聊:用Reflector查看.Net的類的內部實現,解決問題
2、C#中的接口和類有什麼異同。
答:接口是負責功能的定義,項目中通過接口來規範類,操作類以及抽象類的概念!
而類是負責功能的具體實現!
在類中也有抽象類的定義,抽象類與接口的區別在於:
抽象類是一個不完全的類,類裏面有抽象的方法,屬性,也可以有具體的方法和屬性,需要進一步的專業化。
但接口是一個行爲的規範,裏面的所有東西都是抽象的!
一個類只可以繼承一個基類也就是父類,但可以實現多個接口
不同點:
不能直接實例化接口。
接口不包含方法的實現。
接口可以多繼承,類只能單繼承。
類定義可在不同的源文件之間進行拆分。
相同點:
接口、類和結構都可以從多個接口繼承。
接口類似於抽象基類:繼承接口的任何非抽象類型都必須實現接口的所有成員。
接口和類都可以包含事件、索引器、方法和屬性。
基礎知識:接口只能定義方法(只能定義行爲,不能定義實現也就是字段),因爲事件、索引器、屬性本質上都是方法,所以接口中也可以定義事件、索引器、屬性。
3、override與重載(overload)的區別
重載是方法的名稱相同。參數或參數類型不同,進行多次重載以適應不同的需要。重載(overload)是面向過程的概念。
Override 是進行基類中函數的重寫。Override是面向對象的概念
4、屬性和public字段的區別是什麼?調用set方法爲一個屬性設值,然後用get方法讀取出來的值一定是set進去的值嗎?
屬性可以對設值、取值的過程進行非法值控制,比如年齡禁止設值負數,而字段則不能進行這樣的設置。雖然一般情況下get讀取的值就是set設置的值,但是可以讓get讀取的值不是set設置的值的,極端的例子。Public Age{get{return 100;}set{}}。加分的補充回答:用reflector反編譯可以看出,屬性內部本質上就是set_***、get_***方法,詳細參考傳智播客.net培訓視頻中串講.net基礎的部分。
class Person
{
public int Age
{
get
{
return 3;
}
set
{
}
}
}
Person p1 = new Person();
p1.Age = 30;
p1.Age++;
Console.Write(p1.Age);//輸出3
5.請敘述屬性與索引器的區別。
屬性 索引器
通過名稱標識。 通過簽名標識。
通過簡單名稱或成員訪問來訪問。 通過元素訪問來訪問。
可以爲靜態成員或實例成員。 必須爲實例成員。
屬性的 get 訪問器沒有參數。
索引器的 get 訪問器具有與索引器相同的形參表。
屬性的set訪問器包含隱式value參數。 除了value 參數外,索引器的 set 訪問器還具有與索引器相同的形參表。
6、請敘述const與readonly的區別。
每一個class至多隻可以定義一個static構造函數,並且不允許增加訪問級別關鍵字,參數列必須爲空。
爲了不違背編碼規則,通常把static數據成員聲明爲private,然後通過statci property提供讀寫訪問。
const 關鍵字用於修改字段或局部變量的聲明。它指定字段或局部變量的值不能被修改。常數聲明引入給定類型的一個或多個常數。
const數據成員的聲明式必須包含初值,且初值必須是一個常量表達式。因爲它是在編譯時就需要完全評估。
const成員可以使用另一個const成員來初始化,前提是兩者之間沒有循環依賴。
readonly在運行期評估賦值,使我們得以在確保“只讀訪問”的前提下,把object的初始化動作推遲到運行期進行。
readonly 關鍵字與 const 關鍵字不同: const 字段只能在該字段的聲明中初始化。readonly 字段可以在聲明或構造函數中初始化。因此,根據所使用的構造函數,readonly
字段可能具有不同的值。另外,const 字段是編譯時常數,而
readonly 字段可用於運行時常數。
readonly 只能在聲明時或者構造函數裏面初始化,並且不能在 static 修飾的構造函數裏面。
7、在dotnet中類(class)與結構(struct)的異同?
Class可以被實例化,屬於引用類型,是分配在內存的堆上的。類是引用傳遞的。
Struct屬於值類型,是分配在內存的棧上的。結構體是複製傳遞的。加分的回答:Int32、Boolean等都屬於結構體。
8、值類型和引用類型的區別?
1.將一個值類型變量賦給另一個值類型變量時,將複製包含的值。引用類型變量的賦值只複製對對象的引用,而不復制對象本身。
2.值類型不可能派生出新的類型:所有的值類型均隱式派生自 System.ValueType。但與引用類型相同的是,結構也可以實現接口。
3.值類型不可能包含 null 值:然而,可空類型功能允許將 null 賦給值類型。
4.每種值類型均有一個隱式的默認構造函數來初始化該類型的默認值。
10、abstract class和interface有什麼區別?
相同點:
都不能被直接實例化,都可以通過繼承實現其抽象方法。
不同點:
接口支持多繼承;抽象類不能實現多繼承。
接口只能定義行爲;抽象類既可以定義行爲,還可能提供實現。
接口只包含方法(Method)、屬性(Property)、索引器(Index)、事件(Event)的簽名,但不能定義字段和包含實現的方法;
抽象類可以定義字段、屬性、包含有實現的方法。
接口可以作用於值類型(Struct)和引用類型(Class);抽象類只能作用於引用類型。例如,Struct就可以繼承接口,而不能繼承類。
加分的補充回答:講設計模式的時候SettingsProvider的例子。
11、ref與out的區別?
Ref的參數,要求傳遞進來的變量必須聲明,並且賦值
ref應用與內部對外部的值進行改變,out則是內部爲外部變量賦值,out一般用在函數有多個返回值的場所。
Out參數,傳遞到out參數的變量,聲明不需要賦值(賦值也沒有意義),在out參數所在的方法中,out參數必須賦值,並且是在使用前賦值
12、堆和棧的區別?
棧是編譯期間就分配好的內存空間,因此你的代碼中必須就棧的大小有明確的定義;局部值類型變量、值類型參數等都在棧內存中。
堆是程序運行期間動態分配的內存空間,你可以根據程序的運行情況確定要分配的堆內存的大小。
13、XML 與 HTML 的主要區別
1. XML是區分大小寫字母的,HTML不區分。
2. 在HTML中,如果上下文清楚地顯示出段落或者列表鍵在何處結尾,那麼你可以省略</p>或者</li>之類的結束 標記。在XML中,絕對不能省略掉結束標記。
HTML:<img src="1.jpg"><br><br>
XML:<img src="1.jpg"></img><br/><br/>
3. 在XML中,擁有單個標記而沒有匹配的結束標記的元素必須用一個 / 字符作爲結尾。這樣分析器就知道不用 查找結束標記了。
4. 在XML中,屬性值必須分裝在引號中。在HTML中,引號是可用可不用的。
5. 在HTML中,可以擁有不帶值的屬性名。在XML中,所有的屬性都必須帶有相應的值。
XML是用來存儲和傳輸數據的
HTML是用來顯示數據的
如果使用了完全符合XML語法要求的HTML,那麼就叫做符合XHTML標準。符合XHTML標準的頁面有利於SEO。
14、string str = null 與 string str = “”說明其中的區別。
答:string str = null 是不給他分配內存空間,而string str = \"\" 給它分配長度爲空字符串的內存空間。 string str = null沒有string對象,string str = “”有一個字符串對象。
string s3 = string.Empty;//反編譯發現,string.Empty就是在類構造函數中 Empty = "";
15、StringBuilder 和 String 的區別?
答:String 在進行運算時(如賦值、拼接等)會產生一個新的實例,而 StringBuilder 則不會。所以在大量字符串拼接或頻繁對某一字符串進行操作時最好使用 StringBuilder,不要使用 String
如果要操作一個不斷增長的字符串,儘量不用String類,改用StringBuilder類。兩個類的工作原理不同:String類是一種傳統的修改字符串的方式,它確實可以完成把一個字符串添加到另一個字符串上的工作沒錯,但是在.NET框架下,這個操作實在是划不來。因爲系統先是把兩個字符串寫入內存,接着刪除原來的String對象,然後創建一個String對象,並讀取內存中的數據賦給該對象。這一來二去的,耗了不少時間。而使用System.Text命名空間下面的StringBuilder類就不是這樣了,它提供的Append方法,能夠在已有對象的原地進行字符串的修改,簡單而且直接。當然,一般情況下覺察不到這二者效率的差異,但如果你要對某個字符串進行大量的添加操作,那麼StringBuilder類所耗費的時間和String類簡直不是一個數量級的。
16、您在什麼情況下會用到虛方法?它與接口有什麼不同?
答案:子類重新定義父類的某一個方法時,必須把父類的方法定義爲virtual
在定義接口中不能有方法體,虛方法可以。
實現時,子類可以不重新定義虛方法,但如果一個類繼承接口,那必須實現這個接口。
17、string、String;int、Int32;Boolean、bool的區別
String、Int32、Boolean等都屬於.Net中定義的類,而string、int、bool相當於C#中對這些類定義的別名。CTS。
18、.Net、ASP.Net、C#、VisualStudio之間的關係是什麼?
答:.Net一般指的是.Net Framework,提供了基礎的.Net類,這些類可以被任何一種.Net編程語言調用,.Net Framework還提供了CLR、JIT、GC等基礎功能。
ASP.Net是.Net中用來進行Web開發的一種技術,ASP.Net的頁面部分寫在aspx 文件中,邏輯代碼通常通過Code-behind的方式用C#、VB.Net等支持.Net的語言編寫。
C#是使用最廣泛的支持.Net的編程語言。除了C#還有VB.Net、IronPython等。
VisualStudio是微軟提供的用來進行.Net開發的集成開發環境(IDE),使用VisualStudio可以簡化很多工作,不用程序員直接調用csc.exe等命令行進行程序的編譯,而且VisualStudio提供了代碼自動完成、代碼高亮等功能方便開發。除了VisualStudio,還有SharpDevelop、MonoDevelop等免費、開源的IDE,VisualStudio Express版這個免費版本。
概念說明型
1、簡述 private、 protected、 public、 internal 修飾符的訪問權限。
private : 私有成員, 在類的內部纔可以訪問。
protected : 保護成員,該類內部和繼承類中可以訪問。
public : 公共成員,完全公開,沒有訪問限制。
internal: 當前程序集內可以訪問。
2:new有幾種用法
第一種:new Class();
第二種:覆蓋方法
public new XXXX(){}
第三種:new 約束指定泛型類聲明中的任何類型參數都必須有公共的無參數構造函數。
3、用sealed修飾的類有什麼特點
答 sealed 修飾符用於防止從所修飾的類派生出其它類。如果一個密封類被指定爲其他類的基類,則會發生編譯時錯誤。密封類不能同時爲抽象類。
sealed 修飾符主要用於防止非有意的派生,但是它還能促使某些運行時優化。具體說來,由於密封類永遠不會有任何派生類,所以對密封類的實例的虛擬函數成員的調用可以轉換爲非虛擬調用來處理。String就是用sealed修飾的,所以不能被繼承。
4、請編程遍歷頁面上所有TextBox控件並給它賦值爲string.Empty?
答:
foreach
(System.Windows.Forms.Control control in this.Controls)
{
if
(control is System.Windows.Forms.TextBox)
{
System.Windows.Forms.TextBox tb =
(System.Windows.Forms.TextBox)control ;
tb.Text = String.Empty ;
}
}
5、在.net中,配件的意思是?
答:程序集。(中間語言,源數據,資源,裝配清單)
6、C#中索引器是否只能根據數字進行索引?是否允許多個索引器參數?
參數的個數和類型都是任意的。加分的補充回答:用reflector反編譯可以看出,索引器的內部本質上就是set_item、get_item方法。
基礎知識:
索引的語法:
public string this[string s],通過get、set塊來定義取值、賦值的邏輯
索引可以有多個參數、參數類型任意
索引可以重載。
如果只有get沒有set就是隻讀的索引。
索引其實就是set_Item、get_Item兩個方法。
7.概述反射和序列化
反射:程序集包含模塊,而模塊包含類型,類型又包含成員。反射則提供了封裝程序集、模塊和類型的對象。您可以使用反射動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型。然後,可以調用類型的方法或訪問其字段和屬性
序列化:序列化是將對象轉換爲容易傳輸的格式的過程。例如,可以序列化一個對象,然後使用 HTTP 通過 Internet 在客戶端和服務器之間傳輸該對象。在另一端,反序列化將從該流重新構造對象。
8、關於拆箱裝箱:
1)什麼是裝箱(boxing)和拆箱(unboxing)? (*)
Object是引用類型,但是它的子類Int32竟然不能去Object能去的“要求必須是引用類型”
的地方,違反了繼承的原則,所以需要把Int32裝在Object中才能傳遞。
裝箱:從值類型接口轉換到引用類型。
拆箱:從引用類型轉換到值類型。
object obj = null;//引用類型
obj = 1;//裝箱,boxing。把值類型包裝爲引用類型。
int i1 = (int)obj;//拆箱。unboxing
2)下面三句代碼有沒有錯,以inboxing或者unboxing爲例,解釋一下內存是怎麼變化的
int i=10;
object obj = i;
int j = obj;
分析:在inboxing(裝箱)時是不需要顯式的類型轉換的,不過unboxing(拆箱)需要顯式的類型轉換,所以第三行代碼應該改爲:
3 int j = (int)obj;
要掌握裝箱與拆箱,就必須瞭解CTS及它的特點:
NET重要技術和基礎之一的CTS(Common Type System)。CTS是爲了實現在應用程序聲明和使用這些類型時必須遵循的規則而存在的通用類型系統。.Net將整個系統的類型分成兩大類 :值類型和引用類型。
CTS中的所有東西都是對象;所有的對象都源自一個基類——System.Object類型。值類型的一個最大的特點是它們不能爲null,值類型的變量總有一個值。爲了解決值類型不可以爲null,引用類型可以爲null的問題,微軟在.Net中引入了裝箱和拆箱:裝箱就是將值類型用引用類型包裝起來轉換爲引用類型;而從引用類型中拿到被包裝的值類型數據進行拆箱。
object.ReferenceEquals();//用來判斷兩個對象是否是同一個對象
Console.WriteLine(object.ReferenceEquals(3,3));//因爲兩個3被裝到了兩個箱子中,所以是false
Equals ==的關係
9、CTS、CLS、CLR分別作何解釋(*)把英文全稱背過來。
C#和.Net的關係。
C#只是抽象的語言,可以把C#編譯生成Java平臺的二進制代碼,也可以把Java代碼編譯生成.Net平臺的二進制代碼。所以C#只是提供了if、while、+-*/、定義類、int、string等基礎的語法,而Convert.ToInt32、FileStream、SqlConnection、String.Split等都屬於.Net的東西。深藍色是C#的,淺藍色是.Net的。
C# new→IL:newobj
C# string →.Net中的String
類型的差別:.net中的Int32在C#中是int,在VB.Net中是Integer。
語法的差別:IL中創建一個對象的方法是L_0001: newobj instance void 索引.C1::.ctor()
C#中是new C1();VB.net中是 Dim c1 As New C1
CTS:Common Type System 通用類型系統。Int32、Int16→int、String→string、Boolean→bool。每種語言都定義了自己的類型,.Net通過CTS提供了公共的類型,然後翻譯生成對應的.Net類型。
CLS:Common Language Specification 通用語言規範。不同語言語法的不同。每種語言都有自己的語法,.Net通過CLS提供了公共的語法,然後不同語言翻譯生成對應的.Net語法。
CLR:Common Language Runtime 公共語言運行時,就是GC、JIT等這些。有不同的CLR,比如服務器CLR、Linux CLR(Mono)、Silverlight CLR(CoreCLR)。相當於一個發動機,負責執行IL。
10、能用foreach遍歷訪問的對象的要求
需要實現IEnumerable接口或聲明GetEnumerator方法的類型。
11、GC是什麼? 爲什麼要有GC?
C/C++中由程序員進行對象的回收像學校食堂中由學生收盤子,.Net中由GC進行垃圾回收像餐館中店員去回收。
GC是垃圾收集器(Garbage Collection)。程序員不用擔心內存管理,因爲垃圾收集器會自動進行管理。GC只能處理託管內存資源的釋放,對於非託管資源則不能使用GC進行回收,必須由程序員手工回收,一個例子就是FileStream或者SqlConnection需要程序員調用Dispose進行資源的回收。GC不能回收非託管資源,對於非託管資源一般都實現了IDisposable接口,然後使用using關鍵字進行資源的回收。
要請求垃圾收集,可以調用下面的方法:GC.Collect()一般不需要手動調用GC.Collect()。當一個對象沒有任何變量指向(不再能使用)的時候就可以被回收了。
基礎知識:當沒有任何變量指向一個對象的時候對象就可以被回收掉了,但不一定會立即被回收。
object obj = new object();//只有new纔會有新對象
Console.WriteLine(obj);
object obj2 = obj;
obj = null;
obj2 = null;
Console.WriteLine();
12、using關鍵字有什麼用?什麼是IDisposable?
using可以聲明namespace的引入,還可以實現非託管資源的釋放,實現了IDisposiable的類在using中創建,using結束後會自動調用該對象的Dispose方法,釋放資源。Idisosiable類含Close 、Dispose、finalize方法。加分的補充回答:using其實等價於try……finally,用起來更方便。
13、傳入某個屬性的set方法的隱含參數的名稱是什麼?
value,它的類型和屬性所聲名的類型相同。
14、說出一些常用的類、接口,請各舉5個
要讓人家感覺你對.Net開發很熟,所以,不能僅僅只列誰都能想到的那些東西,要多列你在做項目中涉及的那些東西。就寫你最近寫的那些程序中涉及的那些類。
常用的類:StreamReader、WebClient、Dictionary<K,V>、StringBuilder、SqlConnection、FileStream、File、Regex、List<T>
常用的接口:IDisposable、IEnumerable、IDbConnection、IComparable、ICollection、IList、IDictionary
要出乎意料!不要僅僅完成任務!筆試不是高考!處處要顯出牛!
是非型
1、不是說字符串是不可變的嗎?string s="abc";s="123"不就是變了嗎?
String是不可變的在這段代碼中,s原先指向一個String對象,內容是 "abc",然後我們將s指向"123",那麼s所指向的那個對象是否發生了改變呢?答案是沒有。這時,s不指向原來那個對象了,而指向了另一個 String對象,內容爲"123",原來那個對象還存在於內存之中,只是s這個引用變量不再指向它了。
2、是否可以從一個static方法內部發出對非static方法的調用?
不可以。因爲非static方法是要與對象關聯在一起的,必須創建一個對象後,纔可以在該對象上進行方法調用,而static方法調用時不需要創建對象,可以直接調用。也就是說,當一個static方法被調用時,可能還沒有創建任何實例對象,如果從一個static方法中發出對非static方法的調用,那個非static方法是關聯到哪個對象上的呢?這個邏輯無法成立,所以,一個static方法內部不能發出對非static方法的調用。
3、C#支持多重繼承麼?
類之間不支持,接口之間支持。類對接口叫做實現,不叫繼承。 類是爹、接口是能力,能有多個能力,但不能有多個爹。
4、public static const; int A = 1;這段代碼有錯誤麼?
錯誤:const不能被修飾爲static ;因爲定義爲常量 (const )後就是靜態的(static )。
5、int、DateTime、string是否可以爲null?
null表示“不知道”,而不是“沒有”。沒有年齡和不知道年齡是不一樣。
數據庫中null不能用0表示。0歲和不知道多少歲不一樣。
Sex is zero。《色即是空》
//int i1 = null;
//int? i2 = null;//值類型後加?就成了可空數據類型
////int i3 = i2;//所以把可空的賦值給一定不能爲空的會報錯。
//int i4 = (int)i2;//可以顯式轉換,由程序員來保證“一定不爲空”
//int? i5 = i4;//一定會成功!
//using()→try{]catch{}finally{}
//int?是微軟的一個語法糖。是一種和int沒有直接關係的Nullable類型
Nullable<int> d1 = new Nullable<int>();//int? d1=null;
Nullable<int> d2 = new Nullable<int>(3);//int? d2=3;
Console.WriteLine(d1==null);
int、DateTime不能,因爲其爲Struct類型,而結構屬於值類型,值類型不能爲null,只有引用類型才能被賦值null。string可以爲null。
C#中int等值類型不可以爲null、而數據庫中的int可以爲null,這就是糾結的地方。int?就變成了可空的int類型。bool?、DateTime?
int i1 = 3;
int? i2 = i1;
//int i3 = i2;//不能把可能爲空的賦值給一定不能爲空的變量
int i3 = (int)i2;//顯式轉換
可空數據類型經典應用場景:三層中的Model屬性的設計。
int?翻譯生成.Net的Nullable<int>,CTS。
6、能否脫離VS用類似editplus的工具手寫代碼?你覺得如何才能提高代碼的效率和性能?
可以,使用CSC.exe 來編譯.cs文件!
可以根據業務流程、業務數據的特點進行優化,比如可以採用緩存、索引、表驅動等來提升代碼的效率和性能,同時不要進行無意義的代碼優化,重點優化系統的性能瓶頸。
7、利用operator聲明且僅聲明瞭==,有什麼錯誤麼? 要同時修改Equale和GetHash() ? 重載了"==" 就必須重載 "!="
8、short s=1;s=s+1;有錯嗎?short s=1;s+=1;有錯嗎?
答案:第一個有錯,因爲1是int類型,int+short結果是int,無法隱式轉換,改爲s = (short)(s + 1);就可以了。
第二個沒錯,經過反編譯發現編譯器自動優化成s = (short)(s + 1);
代碼分析型
1、
static void Main(string[] args)
{
Console.WriteLine(GetIt());
Console.ReadKey();
}
static int GetIt()
{
int i = 8;
try
{
i++;
Console.WriteLine("a");
return i;//把返回值設定爲i,然後“儘快”返回(沒啥事就回去吧)
}
finally
{
Console.WriteLine("b");
i++;
}
}
上面程序的執行結果是ab9
try {}裏有一個return語句,那麼緊跟在這個try後的finally {}裏的代碼會不會被執行,什麼時候被執行?
會執行,在return後執行。
static void Main(string[] args)
{
//Console.WriteLine(GetIt());
Console.WriteLine(GetPerson().Age);
Console.ReadKey();
}
static int GetIt()
{
int i = 8;
try
{
i++;
Console.WriteLine("a");
return i;//把返回值設定爲i,然後“儘快”返回(沒啥事就回去吧。搞完就走)
}
finally
{
Console.WriteLine("b");
i++;
}
}
static Person GetPerson()
{
Person p = new Person();
p.Age = 8;
try
{
p.Age++;
Console.WriteLine("a");
return p;//把返回值設定爲i,然後“儘快”返回(沒啥事就回去吧。搞完就走)
}
finally
{
Console.WriteLine("b");
p.Age++;
}
}
加分的補充回答(也助記):讀取數據庫中數據的條數的程序
public int QueryCount()
{
…..
try
{
return cmd.ExecuteScalar();
}
finally
{
cmd.Dispose();
}
}
先執行cmd.ExecuteScalar(),把返回值暫時存起來,然後再去執行finally(錢放在這,我去劫個色),然後把返回值返回。return都是最後執行,但是return後的表達式的計算則是在finally之前。
如果C#設計的是先執行cmd.Dispose()再執行return就會出現return執行失敗了,因爲cmd已經Dispose了。
2、下面的程序執行結果是什麼?
class Person
{
public int Age { get; set; }
}
int i1 = 20;
int i2 = i1;
i1++;
Console.WriteLine(i2);
Person p1 = new Person();
p1.Age = 20;
Person p2 = p1;
p1.Age++;
Console.WriteLine(p2.Age);
答案:
20
21
解釋:引用類型和值類型的區別。
3、下面程序的執行結果是什麼?
int i = 10;
Console.WriteLine(i++);
Console.WriteLine(++i);
Console.WriteLine(i=20);
Console.WriteLine(i==20);
答案:
10
12
20
True
解答:前兩個參考第80題,i++表達式的值爲i自增之前的值,所以打印10,執行完成後i變成11,執行++i的時候表達式的值爲自增以後的值12。C#中賦值表達式的值爲變量被賦值的值,因此最後一個就輸出i賦值後的值20
while((line=reader.ReadLine())!=null)
{
}
4、下面程序的執行結果是什麼?
public struct Point
{
public int x;
public int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
Point p1 = new Point(100, 100);
Point p2 = p1;
p1.x = 200;
Console.WriteLine("{0},{1}", p1.x, p2.x);
答案:
200,100
解答:結構體是複製傳遞的。
5、請編程遍歷WinForm頁面上所有TextBox控件並給它賦值爲string.Empty?
答:
foreach (System.Windows.Forms.Control control in this.Controls)
{
if (control is System.Windows.Forms.TextBox)
{
System.Windows.Forms.TextBox tb = (System.Windows.Forms.TextBox)control ;
tb.Text = String.Empty ;
}
}
6、
int i=2000;
object o=i;
i=2001;
int j=(int)o;
Console.WriteLine("i={0},o={1},j={2}",i,o,j);
輸出的結果是:
7、一個數組:1,1,2,3,5,8,13,21...+m,求第30位數是多少?用遞歸實現;
寫遞歸要確定兩個:遞歸的終止條件;遞歸表達式。
解答:總結遞歸規律:F(n)=F(n-2)+F(n-1) Fibonacci數列
static int F(int n)
{
if (n == 1)
{
return 1;
}
if (n == 2)
{
return 1;
}
return F(n - 2) + F(n - 1);
}
非遞歸(有bug嗎?),遞歸算法的缺點:測試大數據
int n = Convert.ToInt32(Console.ReadLine());
if(n<=0)
{Console.WRiteLine("必須大於0");return;}
if(n==1) //時刻注意邊界值!!!
{
Console.WriteLine("1");
return;
}
int[] data =new int[n];
data[0] = 1;
data[1] = 1;
for(int i=2;i<n;i++)
{
data[i] = data[i-1]+data[i-2];
}
Console.WriteLine(data[n-1]);
上面程序的時間複雜度爲O(n),空間複雜度爲O(n)
參考:
算法複雜度:時間複雜度:算法運行需要消耗的時間的數量級、空間複雜度:算法運行需要消耗的內存的數量級。
消耗的時間或者內存隨着問題規模的擴大而成正比增加,就是O(n)。
消耗的時間或者內存隨着問題規模的擴大而不變,就是O(1)。
消耗的時間或者內存隨着問題規模的擴大而n*n增加,就是O(n*n)
算法複雜度只考慮最差情況(從一個數組中找出第一個大於10的數,時間複雜度爲O(n)),並且算法複雜度忽略常量和低階。把數組數一遍和數兩遍的時間複雜度都是O(n)。把長度爲n的數組數n/2遍的時間複雜度還是O(n*n)。
上課時把數組前後顛倒的算法的時間複雜度爲O(n),空間複雜度爲O(1)。
8、產生一個int數組,長度爲100,並向其中隨機插入1-100,並且不能重複。(要求使用兩種方法)
解答:Random類是一個僞隨機數算法,原理:
r(n)=(sed+r(n-1))%100;
class MyRand
{
private int seed;
private int prevNumber = 10;
public MyRand(int seed)
{
this.seed = seed;
}
public int Next()
{
int newRand = (seed + prevNumber) % 100;
prevNumber = newRand;
return newRand;
}
}
生成的隨機數是依賴於上一個的,所以叫“隨機數序列”。,確定的種子產生確定的隨機數序列。
爲了避免每次生成的隨機數序列都一樣,所以一般採用當前系統運行的毫秒數Environment.TickCount做種子。
這就明白爲什麼
//for (int i = 0; i < 10; i++)
//{
// Random rand = new Random();
// Console.WriteLine(rand.Next(100));
//}
是錯的。
經過反編譯,Random類的無參構造函數最終也是調用有參的,傳遞的就是當前毫秒數
public Random() : this(Environment.TickCount)
這就驗證了
//for (int i = 0; i < 10; i++)
//{
// Random rand = new Random();
// Console.WriteLine(rand.Next(100));
//}
爲什麼一樣,或者一半一樣,是因爲在同一毫秒內。
做法1:
List<int> list = new List<int>();
Random rand = new Random();
while (list.Count < 100)
{
int number = rand.Next(1, 101);//>=1,<101
if (!list.Contains(number))//如果list中已經含有這個數,則不插入
{
list.Add(number);
}
}
foreach (int i in list)
{
Console.WriteLine(i);
}
做法2:
先把1-100這100個數按順序放入數組arr,再重複100次下面的操作,生成兩個介於 >=0,<100 之間的隨機數m、n,顛倒arr[m]和arr[n]的數。
int[] arr = new int[100];
//把100個數順序放入
for (int i = 0; i < 100; i++)
{
arr[i] = i + 1;
}
Random rand = new Random();
for (int i = 0; i < 100; i++)
{
//隨機生成兩個位置
int m = rand.Next(0, 100);
int n = rand.Next(0, 100);
//顛倒兩個位置
int temp = arr[m];
arr[m] = arr[n];
arr[n] = temp;
}
效率比第一種高的多,這個只需要N次,而上一種至少需要N*N次
常規筆試題:計算數組{1,1,2,3,5,8....}第30位的值。
解答:斐波那契數列。最前兩個數是1,之後每個數都是前兩個數的和。
f(n)=f(n-2)+f(n-1)
第一種解法:
static int Fib(int n)
{
//面試時要格外注意檢查參數的合法值
//拿個卷面分也是好的
if (n < 0)
{
throw new ArgumentException("n不能爲負數");
}
//return Fib(n - 2) + Fib(n - 1);
if (n == 0 || n == 1)
{
return 1;//遞歸一定要有終止條件
}
else
{
return Fib(n - 2) + Fib(n - 1);
}
}
第二種解法
//效率非常高!
static int Fib2(int n)
{
if (n < 0)
{
throw new ArgumentException("n不能爲負數");
}
if (n == 0)
{
return 1;
}
int[] nums = new int[n+1];//題目不清,我就假定他認爲的30位從0開始
nums[0] = 1;
nums[1] = 1;
//從前往後一個個的加,最後一位就是計算結果
for (int i = 2; i <= n; i++)
{
nums[i] = nums[i - 2] + nums[i - 1];
}
return nums[n];
}
晨飛燕第一次
2、冒泡排序
for (int j = 0; j < nums.Length - 1; j++)
{
for (int i = 0; i < nums.Length - 1 -j; i++)
{
if (nums[i] > nums[i + 1])
{
int temp = nums[i];
nums[i] = nums[i + 1];
nums[i + 1] = temp;
}
}
}
For(int i = 0;i<nums.length-1; i ++)
{
For(int j= 0;j<nums.length-1-i;j++)
{
If(nums[j]>nums[j+1])
{
Int temp=nums[j];
Nums[i]=nums[j+1];
Nums[j+1]=temp;
}
}
}
如果只是調用集合的Sort方法,是不滿足人家要求的!一定要自己寫!
8、有一個10個數的數組,計算其中不重複數字的個數。{3,5,9,8,10,5,3}
工程化的非最優解答:用HashSet
int[] values = { 3, 5, 9, 8, 10, 5, 3 };
HashSet<int> set = new HashSet<int>();
foreach (int i in values)
{
set.Add(i);
}
foreach (int i in set)
{
Console.WriteLine(i);
}
9、下面程序的執行結果是什麼?
class Program
{
static void Main(string[] args)
{
Person p1 = new Person();//1:00
Console.WriteLine(DateTime.Now);
Thread.Sleep(1000 * 10);
Console.WriteLine(DateTime.Now);
Console.WriteLine(p1.BirthDay);
//打印出來的是對象New出來的時間
//因爲字段是對象被new出來的時候初始化的
Console.ReadKey();
}
}
class Person
{
public DateTime BirthDay = DateTime.Now;
}
再難一點
class Person
{
public static int A = 30;
static Person()//靜態構造函數在static字段初始化完成後執行
{//靜態構造函數只執行一次
A++;
}
public int B = A++;//字段的初始化賦值代碼只是在new一個對象的時候執行,而不是每次用字段的時候都執行
}
程序的執行結果是什麼?
Person p1 = new Person();
Console.WriteLine(p1.B);
Console.WriteLine(Person.A);
Console.WriteLine(p1.B);
Console.WriteLine(Person.A);
Person p2 = new Person();
Console.WriteLine(p2.B);
Console.WriteLine(Person.A);
10、下面的代碼中有什麼錯誤嗎?_ abstract override 是不可以一起修飾______
using System;
class A
{
public virtual void F(){
Console.WriteLine("A.F");
}
}
abstract class B:A
{
public abstract override void F();
}
11、當類T只聲明瞭私有實例構造函數時,則在T的程序文本外部,_不可以_(可以 or 不可以)從T派生出新的類,_不可以_(可以 or 不可以)直接創建T的任何實例。
12.下面這段代碼有錯誤麼?case():不行 default;
switch (i){
case():
CaseZero();
break;
case 1:
CaseOne();
break;
case 2:
dufault;
CaseTwo();
break;
}
13.以下代碼段中能否編譯通過?請給出理由。
try
{
}
catch(FileNotFoundException e1)
{
}
catch(Exception e2)
{
}
catch(IOException e3)
{
}
catch
{
}
在ioexception的時候出錯,因爲上一個catch(exception)已經包含了超類型的所有異常
14.class Class1
{
private static int count = 0;
static Class1()
{
count++;
}
public Class1()
{
count++;
}
}
Class1 o1 = new Class1();
Class1 o2 = new Class1();
請問,o1.Count的值是多少?( 3 )
填空選擇題
1、在.Net中所有可序列化的類都被標記爲__[serializable]___?
2、在.Net託管代碼中我們不用擔心內存漏洞,這是因爲有了_ gC __?
3、以下敘述正確的是: B C
A. 接口中可以有虛方法。B. 一個類可以實現多個接口。 C. 接口不能被實例化。 D. 接口中可以包含已實現的方法。
4、對於一個實現了IDisposable接口的類,以下哪些項可以執行與釋放或重置非託管資源相關的應用程序定義的任務?(多選)
( ABC)
A.Close B.Dispose C.Finalize
D.using E.Quit
5、在DOM中,裝載一個XML文檔的方法(B)
a)save方法 b)load方法 c)loadXML方法 d)send方法
6、接口是一種引用類型,在接口中可以聲明(A),但不可以聲明公有的域或私有的成員變量。
a)方法、屬性、索引器和事件; b)方法、屬性信息、屬性; c)索引器和字段; d)事件和字段;
7、Net Framework通過什麼與COM組件進行交互操作?(Interop)
A.Side By SideB.Web Service
C.InteropD.PInvoke
8、Net依賴以下哪項技術實現跨語言互用性?( C )
A.CLR B.CTS C.CLS D.CTT
9、面向對象的語言具有________性、_________性、________性
答:封裝、繼承、多態。
不要背,腦子中要有聯想。
10、接口是一種引用類型,在接口中可以聲明( a),但不可以聲明公有的域或私有的成員變量。
a) 方法、屬性、索引器和事件;
b) 索引器和字段;
c) 事件和字段;
解讀:接口中不能聲明字段只能聲明方法,屬性、索引器和事件 最終都編譯生成方法。因爲字段屬於實現層面的東西,只有存取值的時候纔會用到字段,所以中接口中不能定義字段。
12. 下列關於C#中索引器理解正確的是(c
)
a) 索引器的參數必須是兩個或兩個以上
b) 索引器的參數類型必須是整數型
c) 索引器沒有名字
d) 以上皆非
12、 下面關於XML的描述錯誤的是(d)。
a) XML提供一種描述結構化數據的方法;
b) XML 是一種簡單、與平臺無關並被廣泛採用的標準;
c) XML文檔可承載各種信息;
d) XML只是爲了生成結構化文檔;
13、以下的C#代碼,試圖用來定義一個接口:
public interface IFile
{
int A;
int delFile()
{
A
= 3;
}
void disFile();
}
關於以上的代碼,以下描述錯誤的是(d
)。
a) 以上的代碼中存在的錯誤包括:不能在接口中定義變量,所以int A代碼行將出現錯誤;
b) 以上的代碼中存在的錯誤包括:接口方法delFile是不允許實現的,所以不能編寫具體的實現函數;
c) 代碼void disFile();聲明無錯誤,接口可以沒有返回值;
d) 代碼void disFile();應該編寫爲void disFile(){};
14 不定項選擇:
(1) 以下敘述正確的是: B C
A. 接口中可以有虛方法。B. 一個類可以實現多個接口。 C. 接口不能被實例化。 D. 接口中可以包含已實現的方法。
(3).對於一個實現了IDisposable接口的類,以下哪些項可以執行與釋放或重置非託管資源相關的應用程序定義的任務?(多選) ( ABCD )
A.Close B.Dispose C.Finalize
D.using E.Quit
(4)以下關於ref和out的描述哪些項是正確的?(多選) ( ACD )
A.使用ref參數,傳遞到ref參數的參數必須最先初始化。
B.使用out參數,傳遞到out參數的參數必須最先初始化。
C.使用ref參數,必須將參數作爲ref參數顯式傳遞到方法。
D.使用out參數,必須將參數作爲out參數顯式傳遞到方法。
15、單項選擇:
(1)下列選項中,(C)是引用類型。
a)enum類型 b)struct類型 c)string類型 d)int類型
(3).下列描述錯誤的是(D)
a)類不可以多重繼承而接口可以;
b)抽象類自身可以定義成員而接口不可以;
c)抽象類和接口都不能被實例化;
d)一個類可以有多個基類和多個基接口;
16、聲明一個委託public
delegate int myCallBack(int x); 則用該委託產生的回調方法的原型應該是(b
)。
a) void myCallBack(int x) ;
b) int receive(int num) ;
c) string receive(int x) ;
d) 不確定的;