.NET面試題系列[0] - 寫在前面
.NET面試題系列目錄
- .NET面試題系列[1] - .NET框架基礎知識(1)
- .NET面試題系列[2] - .NET框架基礎知識(2)
- .NET面試題系列[3] - C# 基礎知識(1)
- .NET面試題系列[4] - C# 基礎知識(2)
- .NET面試題系列[5] - 垃圾回收:概念與策略
- .NET面試題系列[6] - 反射
- .NET面試題系列[7] - 委托與事件
- .NET面試題系列[8] - 泛型
- .NET面試題系列[9] - IEnumerable
- .NET面試題系列[10] - IEnumerable的派生類
- .NET面試題系列[11] - IEnumerable<T>的派生類
- .NET面試題系列[12] - C# 3.0 LINQ的準備工作
- .NET面試題系列[13] - LINQ to Object
- .NET面試題系列[14] - LINQ to SQL與IQueryable
- .NET面試題系列[15] - LINQ:性能
- .NET面試題系列[16] - 多線程概念(1)
- .NET面試題系列[17] - 多線程概念(2)
- .NET面試題系列[18] - 多線程同步(1)
- .NET面試題系列[19] - 多線程同步(2)
經過了四年的C#開發工作,我除了獲得到的offer之外,還面試失敗或拒掉了不少offer,加起來面試的次數至少有30次。這些面試有質量很高的,也有泛泛而談的,不同面試有時候還會問到幾乎相同的問題,通過對問題的深入程度,可以大致判斷一家公司和面試官的水平。
跳槽是為了更好的職業規劃和發展。而這需要有強大的業務能力,說服面試官在眾多候選人中選擇你作為勝利者。在若干年的工作學習中,我的水平也慢慢上升,一開始是什么都不會,后來會一些東西,到現在也可以從面試官的問題中,大概了解到他/她的水平如何。
不同類型的公司的面試題目也略有不同,而這些題目要不代表著你面試通過之后可能在實際工作中遇到的問題,要么就是面試官希望通過題目了解你個人的水平如何。例如Facebook,Google,BAT這種綜合性公司在校招的時候,面對的都是應屆大學生,他們沒有什么可能會對搜索引擎十分專精,或者擅長自然語言語義分析。他們會的只是四年的大學計算機教育而已,面試完了之后,這些勝出者也不知道自己會去哪個組做什么方向的工作。所以這時候,給他們出題也不能考搜索引擎,大數據,而只能考最general的內容,那無非就是計算機基礎知識和算法了。
而社招大部分情況下,面試官希望你第一天面試通過,第二天就能上班,并且來之能戰。所以這時候問題基本都是你將來工作可能會遇到的問題。面試官希望你研究過這些問題,并且證明自己能做的比別人更好。當然,面試官也希望你的基礎知識水平牢固,不會在開發,部署,測試等基本流程上一問三不知。例如,我曾經面試過三家公司,他們都希望面試者熟悉WPF或者Winform。所以,其中的兩家問到了工作線程如何修改UI線程控件的內容這個經典問題。對于這個經典的情境,你不僅需要知道如果是按照常規的方法處理會發生什么(UI線程控件的內容只能被擁有控件的線程修改),還要知道怎么解決(Winform使用委托,WPF使用Dispatcher)。而且,你還可以提,如果你的應用是ASP.NET Web Application,則你需要反其道而行之,使用ConfigureAwait強制令系統不進行任何線程的切換。如果面試官知道你在說什么,他/她一定會很開心。如果面試官表現的一臉懵比,你可以在心中為這家公司降低一個檔次。
當你回答問題時,如果你可以答的超乎面試官的意料,則他們給你開的工資可能也會出乎你的意料。例如,對于簡單的問題“如何實現一個單例模式”,如果你只是給出了很簡單的一個構造函數,則面試官可能會覺得你對線程安全不夠敏感 。如果你加了雙重鎖檢查,面試官會問你第一個if是做什么的。如果你也知道,并且還可以解釋清楚,為什么需要雙重鎖檢查,面試官會覺得很滿意。如果你甚至還可以提一句,在很多依賴注入工具中,只需要一個函數就能保證對象在全局都是單例的,例如autofac就有這個功能。面試官將會非常爽,然后話題可能會轉到ioc,或者談談天氣。
外國人問問題有時候不按常理出牌(或者你可以理解為,外國人的常理就是那樣)。我遇到過的比較有趣的問題有:說出你覺得c#好的任意一個理由(我給出的答案是它的語法自然易懂,且比較優雅,背后編譯器作的大量工作你可以不用知道。例證如lambda表達式和async與await關鍵字),為什么c語言被命名為c,說出你自學某語言時看過的書籍,你最喜歡哪種數據結構等。這些問題沒有標準答案,你需要結合事例解釋你的答案。對付這種問題,死記硬背是沒有什么用的,你需要理解或者在背書的基礎上,形成你自己的觀點。
在學習的過程中,我泛泛閱讀了若干本經典書籍,當然還有很多本正放在書架上供著,我可能一輩子也不會去看或者理解的了(例如“編譯原理”)。我也看了很多博客,其中有大量現成的代碼可供直接使用。我認為,作為一個立志奮發圖強的.NET + C# 程序員,應該了解的知識包括:
- .NET框架基礎知識,如.NET框架的核心 – CLR做什么,.NET是如何將源語言編譯成目標語言的,.NET中程序集的作用等等。這些都是背景知識,除了程序集之外基本沒人問,但合格的. NET程序員必須知道。如果你愿意了解更多,可以去拜讀“龍書”(即編譯原理)。我反正在5年之內不打算讀這本書。
- C#的基礎知識,如類型安全,類和結構,垃圾回收,反射,面向對象基本知識等。這些問題比較基礎,但如果深入的問起來還是可以難倒很多很多開發者的。通讀一遍CLR via C#會有很大幫助。
- 委托與事件。雖然任何一本書上都有關于它們的章節,但仍然有很多人對委托的理解僅僅是函數指針這個層次。熟悉委托和事件的開發者,應當知道兩者之間的關系,什么是委托鏈,以及委托是如何做到無處不在的(例如,linq里面就大量充斥著委托)。
- C#從2.0開始的新特性,這是一個極大的話題,主要包括2.0的泛型和可空類型,匿名方法,3.0的linq(以及相關的所有特性,包括閉包),4.0的dynamic,泛型的協變與逆變,4.5的async & await等等。熟悉它們會對代碼有質的影響。任意一本好的介紹C#的書籍都會詳細介紹它們,我個人則是看了Jon Skeet的深入理解C#。這本書包含了很多技術細節,我有三分之一都看不懂。不過個人認為,是否理解那些細節并不會影響你的代碼質量。通常來說,敢在簡歷上寫“熟悉C#”的人,至少應該了解三分之二的C#新特性。
- 數據結構。C#幫你實現了很多常用的數據結構,包括隊列,棧,鏈表。對一些比較常用的數據結構要做到熟悉,并在特定情境時有所取舍。例如,對于經常在中間插入刪除,但沒有什么查找的情境時,選用鏈表而不是List<T>。C#所有的數據結構都基于IEnumerable,我曾經遇到一個面試官問我IEnumerable是做什么的,怎么實現一個IEnumerable。個人認為,后一個問題有點強人所難。不過,如果有人問我List<T>和IList<T>有什么區別,我不會覺得很過分。清華大學出版的“數據結構”足以讓你在這個話題所向披靡。
- 多線程的基本知識。進程和線程的區別,線程的優劣,以及線程的狀態,如何管理線程。對這個問題的深入可以去到計算機最基礎的構造。在C#中,CLR提供了線程池管理線程,不過我們不需要直接和它進行溝通,我們可以通過任務間接的和它溝通。線程有幾種狀態:start,工作中,被阻塞和abort。它們之間的互相轉化構成了同步的幾種方式。你可以去搞一本“深入理解計算機系統”,也許你會對這個問題豁然開朗,不過我才剛剛開始這本書的閱讀。
- 多線程同步。同步方式有很多種,從最經典的lock到它的真身monitor,mutex,semaphore,Event構造,原子操作,死鎖等。考這個的面試官基本都是高手,因為明白這一塊內容很不容易。我面試了這么多家公司,也才就遇到三個問這塊問題的,而且只有一個問的十分深入,剩下的只是考考概念。不過,對于死鎖,很多人喜歡問,他們通常問死鎖產生的條件以及如何避免。加里.納特的“操作系統”中對于死鎖有著十分精彩的論述。通常可以結合哲學家就餐問題回答如何避免死鎖。Windows核心編程這本書也很好,不過我也還沒開始看。
- 異步編程的基本知識。首先,要清楚異步和多線程沒什么關系,它并不是多線程的子集。單線程也可以異步。然后,C#對異步操作提供了幾種方式,例如基于委托,基于事件,以及基于任務。對于每種方式,要清楚它的優缺點(通常缺點都是難以取消或者獲得結果,而基于任務的方式解決了所有問題)。
- 測試。如何編寫單元測試和集成測試,測試的作用,如何隔離和模擬物件,測試驅動開發。不會測試或者不有意在工程中添加測試代碼的工程是令人不安的。持續集成重要的一個原因就是它可以幫你自動把測試都跑一遍。一個無懈可擊的測試十分十分復雜。
- 軟件工程方面的知識。包括版本控制,持續集成等。持續集成已經越來越多地被各個公司使用,以實現快速迭代和交付。如果你可以獨立為公司實現持續集成的從無到有,你將會十分值錢。另外,你之前的公司是實行什么風格的軟件開發流程的?是瀑布還是敏捷?你更喜歡哪種?你對結對編程有什么看法?你認為敏捷有什么不好的地方?
- 關于數據庫的一些基本知識,包括幾個范式,最基本的SQL,表上查詢需要注意的事情(索引怎么放,放哪列等)。另外,你可能也需要知道ORM(Entity Framework)的好處有哪些。大數據,商業智能方向以及數據庫管理員需要重點了解這塊,并且還要加上大量內容,例如事務,數據庫容災,備份,數據倉庫以及ETL。對于不是這些方向的開發者則不需要了解。夢里花落知多少的這篇http://www.rzrgm.cn/anding/p/5281558.html其實已經有點多了,個人覺得(當然,對于DBA來說又太少了)。尤其是對于那些把數據都放在云上,平時拿數據都通過API的互聯網金融公司來說。對于那種公司,你不會SQL都沒關系,因為根本不需要,你也不用建表。
- 常用設計模式。雖然經典的設計模式有20多種,但沒人會變態到讓你把它們都背下來。最常見的無非是單例模式,迭代器模式,工廠,策略模式(ioc),觀察者模式等等,清楚它們怎么實現,什么時候使用它們。另外,對于solid要大致了解,并且在自己設計時,盡量做到。要了解ioc究竟有什么好處。
- 代碼風格和簡單算法。要說看一個人的編程水平如何,最準確的方法就是看代碼了。好的代碼讓你賞心悅目,差的代碼把你逼上梁山。代碼必須要清晰易懂,配上精準的注釋,以至于讓別人基本不需要思考就能理解你要做什么。我非常痛恨的代碼有:一個函數超過100行,命名混亂,瞎選數據結構,算法喜人等。對于算法,如果不是面算法工程師,會最基本的幾個排序和遞歸問題就足夠了,例如,如果你知道C#的Sort方法是如何實現的,并且理解為什么會這么干,或者你知道數據庫的索引用的是B+樹而不是哈希,你的算法水平已經足夠了。(對于谷歌第一題就是徒手翻轉二叉樹我表示不對胃口)不過如果有興趣,可以讀一讀這本“算法”(不是算法導論)https://book.douban.com/subject/10432347/。如果你沒有在大學看過算法導論的話,那么算法導論只有一個功能,那就是可以成功證明你完全不會數學。如果你聲稱你能看懂TAOCP的第一本,請做一個for循環,給世界前10科技公司和投行各發一份簡歷,請相信我,如果你連TAOCP的第一本都看得懂,英語對你的大腦來說簡直就是沒有難度,你甚至只需要寫一句話:我能看懂TAOCP的第一本。
- 能用任意一款腳本語言寫一個猜數字(就是文曲星上的那個游戲)。腳本語言是生活的小幫手,尤其是你需要批處理運行多個程序的時候。我們不需要做到十分熟悉Linux的各個命令,但我們可以在Python,Perl等腳本語言中任選一款,寫一些你認為用C# + VS過于笨重的小程序。當然,如果你還擅長函數式編程語言,那簡直太棒了。
- 你喜歡使用什么工具,讓你的茫茫重構之路變得不那么崎嶇?我個人則是一直在用Resharper。
上面這些如果你基本都會的八九不離十,你在任何一家公司都可以勝任一個后端程序員了。但如果你面試的職位還需要你寫點API,以便讓前端的哥們使用,那你還要粗淺的了解以下內容:
1. Web基礎,包括五層模型,get和post的區別,http協議的一些狀態碼以及IIS的基本設定。對這個話題的深入了解,可以搞一本計算機網絡方面的書籍,里面有詳細的關于五層模型,TCP和IP協議的細節。如果你不是應聘網絡方面的專家級別職位,我不認為它們是十分必要的。當然,如果你立志成為這方面的專家,請遵循http://coolshell.cn/articles/4990.html
2. Web服務。Web服務具有悠久的歷史,最經典的兩種方式SOAP和Restful的區別要知道。另外,微軟對于這兩種方式都給出了自己的實現,即WCF和WebAPI。
3. 對MVC有一定的了解。了解如何利用工具,對你的API進行自動化或非自動化的集成測試。
4. OWIN。微軟的OWIN幫助我們從ASP.NET又臭又長的生命周期解脫出來,從此我們可以定義自己的生命周期。新的ASP.NET Core中也是這樣,生命周期已經成為歷史。我們要了解OWIN基本的工作方式,以及它如何和ioc工具進行配合。另外,通過OWIN,我們的工程可以和IIS解耦,可以用其他的工具代替笨重的IIS。
5. 對于金融交易系統,需要特別關注一下SignalR。它集成了服務器和用戶進行通訊的幾種方式,從常規的輪詢,到服務器主動發送訊息,以及現在常用的WebSocket。它會根據情況自行選用它認為最合適的方式。
上面的內容并不包括前端,這是因為我覺得全棧工程師十分不現實(因為前端的內容和后端幾乎是一樣多的,而光掌握后端的內容,也需要至少3-5年的時間),所以不打算朝這個方向努力,而且我對前端的了解也十分皮毛。當然,只會簡單的HTML和jQuery,可不能稱自己是一個合格的前端工程師。
在漫漫的學習過程中,我們不僅要打牢基礎,還要時刻關注新技術的動向。C# 6推出來一段時間了(雖然其中并沒有什么重大的改進),C# 7也馬上就要問世。ASP.NET Core的推出,把前端的打包和測試拉上了臺面,同時令Angular JS 成為官方前端語言。對于后端來說,也許你沒有機會為公司貢獻Angular JS代碼,但把握住新技術的演進流程,也會對整個知識體系的融會貫通有重要的作用。
我已經寫了不少筆記,雖然大部分都是抄別人的。我在這里也打算效仿博客園眾位前輩,弄一個面試題系列,其中不完全包含上述的所有內容,望各位大大不吝賜教。畢竟互相交流,人人都能受益。那么廢話少說,我們馬上開始。

浙公網安備 33010602011771號