天天看點

c# .net 面試總結

一. sql優化

c# .net 面試總結
c# .net 面試總結
1. 寫明查詢具體某幾列,減少*的使用,表名過長時,盡量使用表的别名 *和列名一樣

2,在業務密集的SQL當中盡量不采用IN操作符,用EXISTS 方案代替。

  in 和 exists的差別: 如果子查詢得出的結果集記錄較少,主查詢中的表較大且又有索引時應該用in, 反之如果外層的主查詢記錄較少,子查詢中的表大,又有索引時使用exists。其實我們區分in和exists主要是造成了驅動順序的改變(這是性能變化的關鍵),如果是exists,那麼以外層表為驅動表,先被通路,如果是IN,那麼先執行子查詢,是以我們會以驅動表的快速傳回為目标,那麼就會考慮到索引及結果集的關系了 ,另外IN時不對NULL進行處理。

  in 是把外表和内表作hash 連接配接,而exists是對外表作loop循環,每次loop循環再對内表進行查詢。一直以來認為exists比in效率高的說法是不準确的。

3、模糊查詢like,盡量少用%
  關鍵詞%yue%,由于yue前面用到了“%”,是以該查詢必然走全表掃描,除非必要,否則不要在關鍵詞前加%,

4, 二者都能使用盡量使用where (與having比較)
  where 先過濾(資料就少了)再分組  
5,盡量使用多表連接配接(join)查詢(避免子查詢)

  子查詢效率特别低,而一般的子查詢都可以由關連查詢來實作相同的功能,關聯查詢的效率要提高很多,是以建議在資料查詢時避免使用子查詢(尤其是在記錄很多時),而最好用關聯查詢來實作。

6,建立索引

  較頻繁地作為查詢條件的字段,唯一性不太差的字段适合建立索引,更新不太頻繁地字段适合建立索引,不會出現在where條件中的字段不該建立索引

7,多使用内部函數提高SQL效率

  例如多用concat連接配接,代替'||' 的符号連接配接

8,應盡量避免在 where 子句中使用 != 或 <> ,in 或 not in

  最好不要給資料庫留NULL,盡可能的使用 NOT NULL填充資料庫 (不然會進行全表掃描,影響效率) 

9,盡可能的使用 varchar/nvarchar 代替 char/nchar (節省字段存儲空間)      

View Code

二.接口和類有什麼異同,抽象類和接口有什麼差別

c# .net 面試總結
c# .net 面試總結
接口和類有什麼異同
不同點:

1、接口不能直接執行個體化。

2、接口隻包含方法或屬性的聲明,不包含方法的實作。

3、接口可以多繼承,類隻能單繼承。

4、類有分部類的概念,定義可在不同的源檔案之間進行拆分,而接口沒有。(這個地方确實不對,接口也可以分部,謝謝@xclin163的指正)

5、表達的含義不同,接口主要定義一種規範,統一調用方法,也就是規範類,限制類,類是方法功能的實作和集合

相同點:

1、接口、類和結構都可以從多個接口繼承。

2、接口類似于抽象基類:繼承接口的任何非抽象類型都必須實作接口的所有成員。

3、接口和類都可以包含事件、索引器、方法和屬性。

抽象類和接口有什麼差別
1、繼承:接口支援多繼承;抽象類不能實作多繼承。

2、表達的概念:接口用于規範,更強調契約,抽象類用于共性,強調父子。抽象類是一類事物的高度聚合,那麼對于繼承抽象類的子類來說,對于抽象類來說,屬于"Is A"的關系;而接口是定義行為規範,強調“Can Do”的關系,是以對于實作接口的子類來說,相對于接口來說,是"行為需要按照接口來完成"。

3、方法實作:對抽象類中的方法,即可以給出實作部分,也可以不給出;而接口的方法(抽象規則)都不能給出實作部分,接口中方法不能加修飾符。

4、子類重寫:繼承類對于兩者所涉及方法的實作是不同的。繼承類對于抽象類所定義的抽象方法,可以不用重寫,也就是說,可以延用抽象類的方法;而對于接口類所定義的方法或者屬性來說,在繼承類中必須重寫,給出相應的方法和屬性實作。

5、新增方法的影響:在抽象類中,新增一個方法的話,繼承類中可以不用作任何處理;而對于接口來說,則需要修改繼承類,提供新定義的方法。

6、接口可以作用于值類型(枚舉可以實作接口)和引用類型;抽象類隻能作用于引用類型。

7、接口不能包含字段和已實作的方法,接口隻包含方法、屬性、索引器、事件的簽名;抽象類可以定義字段、屬性、包含有實作的方法。      

三.C#中的委托是什麼?事件是不是一種委托?

c# .net 面試總結
c# .net 面試總結
什麼是委托?簡單來說,委托類似于 C或 C++中的函數指針,允許将方法作為參數進行傳遞。

C#中的委托都繼承自System.Delegate類型;
委托類型的聲明與方法簽名類似,有傳回值和參數;
委托是一種可以封裝命名(或匿名)方法的引用類型,把方法當做指針傳遞,但委托是面向對象、類型安全的;
事件可以了解為一種特殊的委托,事件内部是基于委托來實作的。      

四.GC與記憶體管理

c# .net 面試總結
c# .net 面試總結
1. 簡述一下一個引用對象的生命周期?
new建立對象并配置設定記憶體
對象初始化
對象操作、使用
資源清理(非托管資源)
GC垃圾回收
2. GC進行垃圾回收時的主要流程是?
① 标記:先假設所有對象都是垃圾,根據應用程式根Root周遊堆上的每一個引用對象,生成可達對象圖,對于還在使用的對象(可達對象)進行标記(其實就是在對象同步索引塊中開啟一個标示位)。

② 清除:針對所有不可達對象進行清除操作,針對普通對象直接回收記憶體,而對于實作了終結器的對象(實作了析構函數的對象)需要單獨回收處理。清除之後,記憶體就會變得不連續了,就是步驟3的工作了。

③ 壓縮:把剩下的對象轉移到一個連續的記憶體,因為這些對象位址變了,還需要把那些Root跟指針的位址修改為移動後的新位址。

6. GC在哪些情況下回進行回收工作?
記憶體不足溢出時(0代對象充滿時)
Windwos報告記憶體不足時,CLR會強制執行垃圾回收
CLR解除安裝AppDomian,GC回收所有
調用GC.Collect
其他情況,如主機拒絕配置設定記憶體,實體記憶體不足,超出短期存活代的存段門限
7. using() 文法是如何確定對象資源被釋放的?如果内部出現異常依然會釋放資源嗎?
using() 隻是一種文法形式,其本質還是try…finally的結構,可以保證Dispose始終會被執行。

8. 解釋一下C#裡的析構函數?為什麼有些程式設計建議裡不推薦使用析構函數呢?
C#裡的析構函數其實就是終結器Finalize,因為長得像C++裡的析構函數而已。

有些程式設計建議裡不推薦使用析構函數要原因在于:第一是Finalize本身性能并不好;其次很多人搞不清楚Finalize的原理,可能會濫用,導緻記憶體洩露,是以就幹脆别用了

9. Finalize() 和 Dispose() 之間的差別?
Finalize() 和 Dispose()都是.NET中提供釋放非托管資源的方式,他們的主要差別在于執行者和執行時間不同:

finalize由垃圾回收器調用;dispose由對象調用。
finalize無需擔心因為沒有調用finalize而使非托管資源得不到釋放,而dispose必須手動調用。
finalize不能保證立即釋放非托管資源,Finalizer被執行的時間是在對象不再被引用後的某個不确定的時間;而dispose一調用便釋放非托管資源。
隻有class類型才能重寫finalize,而結構不能;類和結構都能實作IDispose。
另外一個重點差別就是終結器會導緻對象複活一次,也就說會被GC回收兩次才最終完成回收工作,這也是有些人不建議開發人員使用終結器的主要原因。

10. Dispose和Finalize方法在何時被調用?
Dispose一調用便釋放非托管資源;
Finalize不能保證立即釋放非托管資源,Finalizer被執行的時間是在對象不再被引用後的某個不确定的時間;
11. .NET中的托管堆中是否可能出現記憶體洩露的現象?
是的,可能會。比如:

不正确的使用靜态字段,導緻大量資料無法被GC釋放;
沒有正确執行Dispose(),非托管資源沒有得到釋放;
不正确的使用終結器Finalize(),導緻無法正常釋放資源;
其他不正确的引用,導緻大量托管對象無法被GC釋放;
12. 在托管堆上建立新對象有哪幾種常見方式?
new一個對象;
字元串指派,如string s1=”abc”;
值類型裝箱;      

五.多線程程式設計與線程同步

c# .net 面試總結
c# .net 面試總結
1. 描述線程與程序的差別?
一個應用程式執行個體是一個程序,一個程序内包含一個或多個線程,線程是程序的一部分;
程序之間是互相獨立的,他們有各自的私有記憶體空間和資源,程序内的線程可以共享其所屬程序的所有資源;
2. lock為什麼要鎖定一個參數,可不可鎖定一個值類型?這個參數有什麼要求?
lock的鎖對象要求為一個引用類型。她可以鎖定值類型,但值類型會被裝箱,每次裝箱後的對象都不一樣,會導緻鎖定無效。

對于lock鎖,鎖定的這個對象參數才是關鍵,這個參數的同步索引塊指針會指向一個真正的鎖(同步塊),這個鎖(同步塊)會被複用。

3. 多線程和異步有什麼關系和差別?
多線程是實作異步的主要方式之一,異步并不等同于多線程。實作異步的方式還有很多,比如利用硬體的特性、使用程序或纖程等。在.NET中就有很多的異步程式設計支援,比如很多地方都有Begin***、End***的方法,就是一種異步程式設計支援,她内部有些是利用多線程,有些是利用硬體的特性來實作的異步程式設計。

4. 線程池的優點有哪些?又有哪些不足?
優點:減小線程建立和銷毀的開銷,可以複用線程;也進而減少了線程上下文切換的性能損失;在GC回收時,較少的線程更有利于GC的回收效率。

缺點:線程池無法對一個線程有更多的精确的控制,如了解其運作狀态等;不能設定線程的優先級;加入到線程池的任務(方法)不能有傳回值;對于需要長期運作的任務就不适合線程池。

5. Mutex和lock有何不同?一般用哪一個作為鎖使用更好?
Mutex是一個基于核心模式的互斥鎖,支援鎖的遞歸調用,而Lock是一個混合鎖,一般建議使用Lock更好,因為lock的性能更好。      

 關于線程和并發相關的這邊提供幾篇不錯的文章

  http://www.cnblogs.com/yunfeifei/p/3993401.html

  https://www.cnblogs.com/xinhuawei/p/5398193.html

六.重載與覆寫的差別

c# .net 面試總結
c# .net 面試總結
重載:當類包含兩個名稱相同但簽名不同(方法名相同,參數清單不相同)的方法時發生方法重載。用方法重載來提供在語義上完成相同而功能不同的方法。

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

主要差別:

1、方法的覆寫是子類和父類之間的關系,是垂直關系;方法的重載是同一個類中方法之間的關系,是水準關系。 
2、覆寫隻能由一個方法,或隻能由一對方法産生關系;方法的重載是多個方法之間的關系。 
3、覆寫要求參數清單相同;重載要求參數清單不同。 
4、覆寫關系中,調用那個方法體,是根據對象的類型來決定;重載關系,是根據調用時的實參表與形參表來選擇方法體的。      

七.virtual、sealed、override和abstract的差別

c# .net 面試總結
c# .net 面試總結
virtual申明虛方法的關鍵字,說明該方法可以被重寫
sealed說明該類不可被繼承
override重寫基類的方法
abstract申明抽象類和抽象方法的關鍵字,抽象方法不提供實作,由子類實作,抽象類不可執行個體化。      

八.裝箱與拆箱

c# .net 面試總結
c# .net 面試總結
1.什麼是拆箱和裝箱?

裝箱就是值類型轉換為引用類型,拆箱就是引用類型(被裝箱的對象)轉換為值類型。

2.什麼是箱子?

就是引用類型對象。

3.箱子放在哪裡?

托管堆上。

4.裝箱和拆箱有什麼性能影響?

裝箱和拆箱都涉及到記憶體的配置設定和對象的建立,有較大的性能影響。

5.如何避免隐身裝箱?

編碼中,多使用泛型、顯示裝箱。

6.箱子的基本結構?

上面說了,箱子就是一個引用類型對象,是以她的結構,主要包含兩部分:
值類型字段值;
引用類型的标準配置,引用對象的額外空間:TypeHandle和同步索引塊,關于這兩個概念在本系列後面的文章會深入探讨。

7.裝箱的過程?

1.在堆中申請記憶體,記憶體大小為值類型的大小,再加上額外固定空間(引用類型的标配:TypeHandle和同步索引塊);
2.将值類型的字段值(x=1023)拷貝新配置設定的記憶體中;
3.傳回新引用對象的位址(給引用變量object o)

8.拆箱的過程?

1.檢查執行個體對象(object o)是否有效,如是否為null,其裝箱的類型與拆箱的類型(int)是否一緻,如檢測不合法,抛出異常;
2.指針傳回,就是擷取裝箱對象(object o)中值類型字段值的位址;
3.字段拷貝,把裝箱對象(object o)中值類型字段值拷貝到棧上,意思就是建立一個新的值類型變量來存儲拆箱後的值;      

九.什麼是反射

c# .net 面試總結
c# .net 面試總結
程式集包含子產品,而子產品又包括類型,類型下有成員,反射就是管理程式集,子產品,類型的對象,它能夠動态的建立類型的執行個體,設定現有對象的類型或者擷取現有對象的類型,能調用類型的方法和通路類型的字段屬性。它是在運作時建立和使用類型執行個體;
事例

   public class ReflectionTest {
        
        /// <summary>
        /// 反射名稱
        /// </summary>
        public string ReflectionName { get; set; }

        public string GetName()
        {
            return "張三";
        }
    }


   Type type = typeof(ReflectionTest);
            string name = type.Name;//擷取目前成員的名稱
            string fullName = type.FullName;//擷取類的全部名稱不包括程式集
            string nameSpace = type.Namespace;//擷取該類的命名空間
            var assembly = type.Assembly;//擷取該類的程式集名
            var module = type.Module;//擷取該類型的子產品名            
            var memberInfos = type.GetMembers();//得到所有公共成員
   
 //擷取目前執行代碼的程式集
            Assembly assem = Assembly.GetExecutingAssembly();
            Console.WriteLine(assem.FullName);

            var types = assem.GetTypes();//程式集下所有的類
            Console.WriteLine("程式集包含的類型:");
            foreach (var item in types) {
                Console.WriteLine("類" + item.Name);
            }      

十.資料庫常見的操作--事務,存儲過程,遊标,觸發器等

c# .net 面試總結
c# .net 面試總結
1.維護資料庫的完整性、一緻性、你喜歡用觸發器還是自寫業務邏輯?為什麼?

答:盡可能用限制(包括CHECK、主鍵、唯一鍵、外鍵、非空字段)實作,這種方式的效率最好;其次用觸發器,這種方式可以保證無論何種業務系統通路資料庫都能維持資料庫的完整性、一緻性;最後再考慮用自寫業務邏輯實作,但這種方式效率最低、程式設計最複雜,當為下下之策。

2.什麼是事務?什麼是鎖?

答:事務是指一個工作單元,它包含了一組資料操作指令,并且所有的指令作為一個整體一起向系統送出或撤消請求操作,即這組指令要麼都執行,要麼都不執行。

  鎖是在多使用者環境中對資料的通路的限制。SqlServer自動鎖定特定記錄、字段或檔案,防止使用者通路,以維護資料安全或防止并發資料操作問題,鎖可以保證事務的完整性和并發性。

 3.什麼是索引,有什麼優點?

答:索引象書的目錄類似,索引使資料庫程式無需掃描整個表,就可以在其中找到所需要的資料,索引包含了一個表中包含值的清單,其中包含了各個值的行所存儲的位置,索引可以是單個或一組列,索引提供的表中資料的邏輯位置,合理劃分索引能夠大大提高資料庫性能。

 4.視圖是什麼?遊标是什麼?

答:視圖是一種虛拟表,虛拟表具有和實體表相同的功能,可以對虛拟表進行增該查操作;

    視圖通常是一個或多個表的行或列的子集;

   視圖的結果更容易了解(修改視圖對基表不影響),擷取資料更容易(相比多表查詢更友善),限制資料檢索(比如需要隐藏某些行或列),維護更友善。

   遊标對查詢出來的結果集作為一個單元來有效的處理,遊标可以定位在結果集的特定行、從結果集的目前位置檢索一行或多行、可以對結果集中目前位置進行修改、

 5.什麼是存儲過程?有什麼優點?

答:存儲過程是一組予編譯的SQL語句

    它的優點:1.允許子產品化程式設計,就是說隻需要建立一次過程,以後在程式中就可以調用該過程任意次。

              2.允許更快執行,如果某操作需要執行大量SQL語句或重複執行,存儲過程比SQL語句執行的要快。

               3.減少網絡流量,例如一個需要數百行的SQL代碼的操作有一條執行語句完成,不需要在網絡中發送數百行代碼。

        4.更好的安全機制,對于沒有權限執行存儲過程的使用者,也可授權他們執行存儲過程。

 6.什麼是觸發器?

答:觸發器是一種特殊類型的存儲過程,出發器主要通過事件觸發而被執行的,

  觸發器的優點:1.強化限制,觸發器能夠提供比CHECK限制;

         2.跟蹤變化,觸發器可以跟蹤資料庫内的操作,進而不允許未經允許許可的更新和變化;

         3.聯級運算,比如某個表上的觸發器中包含對另一個表的資料操作,而該操作又導緻該表上的觸發器被觸發      

後續還會慢慢補充,自己碰到或者看到比較好的一些知識都會一一記錄下來  如果有好的知識點 大家記得分享哦

繼續閱讀