c# 曾經面試題
1.c#中public\protect\private\internal修飾符的區別
public 關鍵字是類型和類型成員的訪問修飾符。公共訪問是允許的最高訪問級別,對訪問公共成員沒有限制。
protected 關鍵字是一個成員訪問修飾符。受保護成員在它的類中可訪問並且可由派生類訪問。
private 關鍵字是一個成員訪問修飾符。私有訪問是允許的最低訪問級別。私有成員只有在聲明它們的類和結構體中才是可訪問的。
internal 關鍵字是類型和類型成員的訪問修飾符。只有在同一程序集的文件中,內部類型或成員才是可訪問的。
public 意味著在其後聲明的所有成員對所有的人都可以取。
private 關鍵字意味著除了該類型的創建者和類的內部成員函數之外,任何人都不能存取這些成員。
protect 它與private基本相似,只有一點不同:繼承的結構可以訪問protected成員,但不能訪問private成員。
2.ASP.NEt的幾種傳值方式,及特點http://www.cnblogs.com/zhangkai2237/archive/2012/05/06/2486462.html
常用的較簡單有QueryString,Session,Cookies,Application,Server.Transfer。
一、QueryString
QueryString是一種非常簡單的傳值方式,他可以將傳送的值顯示在瀏覽器的地址欄中。如果是傳遞一個或多個安全性要求不高或是結構簡單的數值時,可以使用這個方法。但是對於傳遞數組或對象的話,就不能用這個方法了。
這種方法的優點:1.使用簡單,對於安全性要求不高時傳遞數字或是文本值非常有效。
這種方法的缺點:1.缺乏安全性,由於它的值暴露在瀏覽器的URL地址中的。
2.不能傳遞對象。
使用方法:1.在源頁面的代碼中用需要傳遞的名稱和值構造URL地址。
2.在源頁面的代碼用Response.Redirect(URL);重定向到上面的URL地址中。
3.在目的頁面的代碼使用Request.QueryString["name"];取出URL地址中傳遞的值。
二、Session:其操作與Application類似,作用於用戶個人,所以,過量的存儲會導致服務器內存資源的耗盡。
優點:1.使用簡單,不僅能傳遞簡單數據類型,還能傳遞對象。
2.數據量大小是不限制的。
缺點:1.在Session變量存儲大量的數據會消耗較多的服務器資源。
2.容易丟失。
使用方法:1.在源頁面的代碼中創建你需要傳遞的名稱和值構造Session變量:Session["Name"]="Value(Or Object)";
2.在目的頁面的代碼使用Session變量取出傳遞的值。Result = Session["Nmae"]
註意:session不用時可以銷毀它,銷毀的方法是:清除一個:Session.Remove("session名");
清除所有:Session.Clear();
三、Cookie:用於在用戶瀏覽器上存儲小塊的信息,保存用戶的相關信息,比如用戶訪問某網站時用戶的ID,用戶的偏好等,用戶下次訪問就可以通過檢索獲得以前的信息。所以Cookie也可以在頁面間傳遞值。Cookie通過HTTP頭在瀏覽器和服務器之間來回傳遞的。Cookie只能包含字符串的值,如果想在Cookie存儲整數值,那麽需要先轉換為字符串的形式。
優點:1.使用簡單,是保持用戶狀態的一種非常常用的方法。比如在購物網站中用戶跨多個頁面表單時可以用它來保持用戶狀態。
缺點:1.常常被人認為用來收集用戶隱私而遭到批評。
2.安全性不高,容易偽造。
使用方法:1.在源頁面的代碼中創建你需要傳遞的名稱和值構造Cookie對象:
四、Application:對象的作用範圍是整個全局,也就是說對所有用戶都有效。它在整個應用程序生命周期中都是有效的,類似於使用全局變量一樣,所以可以在不同頁面中對它進行存取。它和Session變量的區別在於,前者是所有的用戶共用的全局變量,後者是各個用戶獨有的全局變量。
優點:1.使用簡單,消耗較少的服務器資源。
2.不僅能傳遞簡單數據,還能傳遞對象。
3.數據量大小是不限制的。
缺點:1.作為全局變量容易被誤操作。所以單個用戶使用的變量一般不能用application。
使用方法:1.在源頁面的代碼中創建你需要傳遞的名稱和值構造Application變量:Application["Nmae"]="Value(Or Object)";
2.在目的頁面的代碼使用Application變量取出傳遞的值。Result = Application["Nmae"]
註意:常用lock和unlock方法用來鎖定和解鎖,為了防止並發修改。
五、Server.Transfer:其使用Server.Transfer方法把流程從當前頁面引導到另一個頁面中,新的頁面使用前一個頁面的應答流,所以這個方法是完全面象對象的,簡潔有效。
Server.Transfer是從當前的ASPX頁面轉到新的ASPX頁面,服務器端執行新頁並輸出,在新頁面中通過Context.Handler來獲得前一個頁面傳遞的各種數據類型的值、表單數據、QueryString.由於重定向完全在服務器端完成,所以客戶端瀏覽器中的URL地址是不會改變的。調用Server.Transfer時,當前的ASPX頁面終止執行,執行流程轉入另一個ASPX頁面,但新的ASPX頁面仍使用前一ASPX頁面創建的應答流。
ps:比較Server.Transfer和Response.Redirect的區別。
(1)Server.Transfer在服務器端完成,所以客戶端瀏覽器中的URL地址是不會改變的;Response.Redirect是客戶端完成,向服務器端提出新的頁面處理請求,所以客戶端瀏覽器中的URL地址是會改變的。
(2)Server.Transfer在服務器端完成,不需要客戶端提出請求,減少了客戶端對服務器端提出請求。[2]
(3)Server.Transfer只能夠轉跳到本地虛擬目錄指定的頁面,也就是工程項目中的頁面,而Response.Redirect則十分靈活,可以跳轉到任何URL地址。
(4)Server.Transfer可以將前一個頁面的各種類型的值傳到新的頁面;Response.Redirect則只能借助URL中帶參數或是結合上面四種辦法把各種類型的值傳到新的頁面。
優點:1.直接在服務器端重定向,使用簡單方便,減少了客戶端對服務器端提出請求。
2.可以傳遞各種數據類型的值和控件的值。
缺點:1.客戶端瀏覽器中的URL地址是不改變,會導致在新的頁面可能出現一些意想不到的問題。比如如果源頁面和目的頁面不在同一個虛擬目錄或其子目錄下,那麽使用相對路徑的圖片、超鏈接都會導致錯誤的指向。
使用方法:1.在源頁面的代碼中,使用Page類的Server.Transfer跳到另一個頁面傳遞頁面數據:Server.Transfer("b.aspx","false")。
2.在目的頁面中,使用Context.Handler來接收數據:FormerPage formerPage = (FormerPage)Context.Handler; 然後用formerPage的屬性和方法來獲取前一個頁面的值,或者直接用Context.Items["myParameter "]
3.debug build和release build的區別
Debug 通常稱為調試版本,它包含調試信息,並且不作任何優化,便於程序員調試程序。Release 稱為發布版本,它往往是進行了各種優化,使得程序在代碼大小和運行速度上都是最優的,以便用戶很好地使用。
Debug和Release的區別,還在於一組編譯選項(這裏省略...),實際上,Debug和Release並沒有本質的界限,他們只是一組編譯選項的集合,編譯器只是按照預定的選項行動。事實上,我們甚至可以修改這些選項,從而得到優化過的調試版本或是帶跟蹤語句的發布版本。
只有Debug版的程序才能設置斷點、單步執行、使用TRACE/ASSERT等調試輸出語句。Release不包含任何調試信息,所以體積小、運行速度快。
4.a.equals(b)與a==b是否相同
對於值類型相同,對於引用類型不同,equals是內容,==是地址
5.get和post的區別
get一般為鏈接方式,post一般為按鈕方式。
6.什麽叫做SQL註入,如何防止?請舉例說明。
答:利用sql關鍵字對網站進行攻擊。過濾關鍵字‘等
7.string和stringBuilder的區別
String是不可改變的,沒事使用String類中的方法時,都要在內存中創建一個新的字符串對象,就是需要為該對象分配新的空間。需要對字符串執行重復修改的情況下,String對象相關的系統開銷會非常昂貴。在需要對字符串執行重復修改的情況下,可以使用StringBuild類
算法題:
-
取出int數組中最大的10個數
2. string[]的字典排序
3. 現有一int類型數值,想用“,”以N位分割表示輸出(例:int val=18943232,想以18,943,232格式輸出,其中相隔3位數相隔是變量N),請寫出關鍵算法
sql知識
1.索引的作用,主鍵是索引麽?聚集索引和非聚集索引的區別
2.維護數據庫的完整性和一致性,你喜歡用觸發器還是自寫業務邏輯?為什麽?
3.對於數據庫的查詢優化,應該從哪幾方面考慮?
-
一組指定的字符串,統計出該串各字符出現的次數,並打印出出現次數最多的那個字符
string str = "jintiantianqihaoqinglang";
Dictionary<char,int> dic=new Dictionary<char,int>();
foreach (char ch in str)
{
if (dic.Keys.Contains(ch))
{
dic[ch]++;
}
else
{
dic.Add(ch, 1);
}
2.C#中關鍵字new有幾種用法,using有幾種用法
using的用法:1.using+ 命名空間
2.using別名。using + 別名 = 包括詳細命名空間信息的具體的類型。
using
aClass = NameSpace1.MyClass;
using
bClass = NameSpace2.MyClass;
aClass my1 = new aClass();
bClass my2 = new bClass();
3.using語句,定義一個範圍,在範圍結束時處理對象。
場景:
當在某個代碼段中使用了類的實例,而希望無論因為什麽原因,只要離開了這個代碼
段就自動調用這個類實例的Dispose。 要達到這樣的目的,用try...catch來捕捉異
常也是可以的,但用using也很方便。
new的用法:
1)new 運算符:用於創建對象和調用構造函數。這種大家都比較熟悉,沒什麽好說的了。
2)new 修飾符:在用作修飾符時,new 關鍵字可以顯式隱藏從基類繼承的成員。
BaseA中有變量X,方法Invoke()和 TrueValue(), DerivedB用new顯示從繼承基類成員
public class DerivedB : BaseA
{
new public int x = 2;
new public void Invoke()
{
Console.WriteLine(x.ToString());
}
new public int TrueValue
{
get { return x; }
set { x = value; }
}
}
3)new 約束:用於在泛型聲明中約束可能用作類型參數的參數的類型。
AOP: Aspect Oriented Programming 面向切面編程。
面向切面編程(也叫面向方面):Aspect Oriented Programming(AOP),是目前軟件開發中的一個熱點。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。
AOP是OOP的延續,是(Aspect Oriented Programming)的縮寫,意思是面向切面(方面)編程。
主要的功能是:日誌記錄,性能統計,安全控制,事務處理,異常處理等等。
主要的意圖是:將日誌記錄,性能統計,安全控制,事務處理,異常處理等代碼從業務邏輯代碼中劃分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導業務邏輯的方法中,進而改 變這些行為的時候不影響業務邏輯的代碼。
可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,AOP可以說也是這種目標的一種實現。
假設把應用程序想成一個立體結構的話,OOP的利刃是縱向切入系統,把系統劃分為很多個模塊(如:用戶模塊,文章模塊等等),而AOP的利刃是橫向切入系統,提取各個模塊可能都要重復操作的部分(如:權限檢查,日誌記錄等等)。由此可見,AOP是OOP的一個有效補充。
註意:AOP不是一種技術,實際上是編程思想。凡是符合AOP思想的技術,都可以看成是AOP的實現。
4.如果網站打開緩慢,如何定位原因?如何優化?
5.MSSQL的鎖機制
共享鎖
共享 (S) 鎖允許並發事務讀取 (SELECT) 一個資源。資源上存在共享 (S) 鎖時,任何其它事務都不能修改數據。一旦已經讀取數據,便立即釋放資源上的共享 (S) 鎖,除非將事務隔離級別設置為可重復讀或更高級別,或者在事務生存周期內用鎖定提示保留共享 (S) 鎖。
更新鎖
更新 (U) 鎖可以防止通常形式的死鎖。一般更新模式由一個事務組成,此事務讀取記錄,獲取資源(頁或行)的共享 (S) 鎖,然後修改行,此操作要求鎖轉換為排它 (X) 鎖。如果兩個事務獲得了資源上的共享模式鎖,然後試圖同時更新數據,則一個事務嘗試將鎖轉換為排它 (X) 鎖。共享模式到排它鎖的轉換必須等待一段時間,因為一個事務的排它鎖與其它事務的共享模式鎖不兼容;發生鎖等待。第二個事務試圖獲取排它 (X) 鎖以進行更新。由於兩個事務都要轉換為排它 (X) 鎖,並且每個事務都等待另一個事務釋放共享模式鎖,因此發生死鎖。
若要避免這種潛在的死鎖問題,請使用更新 (U) 鎖。一次只有一個事務可以獲得資源的更新 (U) 鎖。如果事務修改資源,則更新 (U) 鎖轉換為排它 (X) 鎖。否則,鎖轉換為共享鎖。
排它鎖
排它 (X) 鎖可以防止並發事務對資源進行訪問。其它事務不能讀取或修改排它 (X) 鎖鎖定的數據。
意向鎖
意向鎖表示 SQL Server 需要在層次結構中的某些底層資源上獲取共享 (S) 鎖或排它 (X) 鎖。例如,放置在表級的共享意向鎖表示事務打算在表中的頁或行上放置共享 (S) 鎖。在表級設置意向鎖可防止另一個事務隨後在包含那一頁的表上獲取排它 (X) 鎖。意向鎖可以提高性能,因為 SQL Server 僅在表級檢查意向鎖來確定事務是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務是否可以鎖定整個表。
意向鎖包括意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
http://www.jb51.net/article/40631.htm、
-
類中的函數不僅能存取類中的私有數據,而且可以存取類的靜態成員數據(√)
-
==與Equals
對於值類型,如果對象的值相等,則相等運算符 (==) 返回 true,否則返回 false。對於string 以外的引用類型,如果兩個對象引用同一個對象,則 == 返回 true。對於 string 類型,== 比較字符串的值。
==操作比較的是兩個變量的值是否相等。
equals()方法比較的是兩個對象的內容是否一致.equals也就是比較引用類型是否是對同一個對象的引用。
class Program
{
static void Main(string[] args)
{
string a = new string(new char[] { ‘H‘, ‘E‘, ‘L‘, ‘L‘, ‘O‘ });
string b = new string(new char[] { ‘H‘, ‘E‘, ‘L‘, ‘L‘, ‘O‘ });
Console.WriteLine(a == b); //True
Console.WriteLine(a.Equals(b)); //True
object g = a;
object h = b;
Console.WriteLine(g == h); //False
Console.WriteLine(g.Equals(h)); //True
Person p1 = new Person("jia");
Person p2 = new Person("jia");
Console.WriteLine(p1 == p2); //False
Console.WriteLine(p1.Equals(p2)); //False
Person p3 = new Person("jia");
Person p4 = p3;
Console.WriteLine(p3 == p4); //True
Console.WriteLine(p3.Equals(p4)); //True
Console.ReadKey();
}
}
class Person
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Person(string name)
{
this.name = name;
}
}
總結:
a.值類型和引用類型
值類型存儲在棧中,而引用類型的變量在棧僅僅是存儲引用類型變量的地址,而其本身則存儲在堆中。
==比較的是兩個變量的值是否相等,對於引用類型變量表示的是兩個變量在堆中存儲的地址是否相同,及棧中內容是否相同
equals操作表示的兩個變量是否是對同一對象的引用,即堆中的內容是否相同
b.對於object g 和object h 時內存中兩個不同的對象所以在棧中的內容是不同的,故不相等。而g.equals(h)用的是string 的equals()方法故相等。如果將字符串a和b做這樣的修改:string a=”aa“;string b="aa" 則g和h的兩個比較都是相等的。這事因為系統並沒有給字符串b分配內存,只是將”aa“指向了b。所以a和b執行的是同一個字符串。
c.類p1和p2
也是內存中兩個不同的對象,所以在內存中的地址肯定不相同,故P1==P2會返回false,又因為p1和p2又是不同對象的引用,所以p1.equals(p2)將返回false/
d.類P3和P4
p4=p3,P3將對對象的引用賦給了P4,P3和P4是對同一個對象的引用,所以兩個比較都返回了true
e.重新類Person中的equals方法後,p1.equals(p2)將返回True.
class Person
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Person(string name)
{
this.name = name;
}
public override bool Equals(object obj)
{
if (!(obj is Person))
return false;
Person per = (Person)obj;
return this.Name == per.Name;
}
}
3. 數據庫的主鍵最多只有一個,但可以有很多的唯一鍵
abstract, extern, or partial 在類中不進行實現
4.接口可以繼承接口,抽象類可以實現接口,但抽象類不能繼承實體類
抽象類和接口的區別:http://kb.cnblogs.com/page/41836/
抽象類:特殊的類,不能被實例化,除此之外,具有類的特性。重要的是抽象類可以包括抽象方法,這是普通類所不能的。抽象方法只能聲明於抽象類中,且不包括任何實現(abstract, extern, or partial 在類中不進行實現),派生類必須覆蓋它們。另外抽象類可以派生自一個抽象類,可以覆蓋基類的抽象方法也可以不覆蓋,如果不覆蓋,則其派生類必須覆蓋它們。
接口:接口是引用類型,和抽象類的相似之處
-
不能實例化;2.包含未實現的方法聲明,3.派生類必須實現未實現的方法,抽象類是抽象方法,接口則是所有成員(不僅是方法包括其他成員)
接口還有如下特性:接口除了包含方法之外,還可以包括屬性、索引器、事件,而且這些成員都被定義為共有的。除此之外,不能包含任何其他成員,例如:常量,域,構造函數,析構函數,靜態成員。
抽象類與接口的區別:
-
類是對對象的抽象,可以把抽象類理解為把類當對象,抽象成的類叫做抽象類。而接口只是 一個行為的規範或規定。抽象類更多的是定義在一系列緊密相關的類間,而接口大多是關系疏松但都實現某一功能的類中
-
接口基本不具備繼承的任何具體特點,它僅僅承諾了能夠調用的方法
-
一個類一次可以實現若幹個接口,但是只能擴展一個父類
-
接口可以用於支持回調,而繼承並不具備 這個特點
-
抽象類不能被密封
-
抽象類實現的具體方法默認為虛的,但實現接口的類中的接口方法默認為非虛的 ,自己可以聲明為虛的
-
接口與非抽象類類似,抽象類也必須為在該類的基類列表中列出的接口的所有成員提供它自己的實現。但是,允許抽象類將接口方法映射到抽象方法上
-
抽象類實現了OOP的一個原則,把可變的與不可變的分離。接口和抽象類就是定義為不可變的,而把可變的放到子類去實現
-
好的接口定義應該具有專一功能性,而不是多功能的,否則造成接口汙染。如果一個類只實現了這個接口中的一個功能,而不得不去實現接口中的其他方法,這就叫接口汙染
-
如果抽象類實現接口,則可以把接口中方法映射到抽象類中作為抽象方法而不必實現,而在抽象類的子類中實現接口中方法。
抽象類和接口的使用:
1. 如果預計要創建組件的多個版本,則創建抽象類。抽象類提供簡單的方法來控制組件版本
2. 如果創建的功能要在大範圍的全異對象中使用,則使用接口,如果要設計小而簡練的功能塊,則使用接口
3. 如果要設計大的功能單元,則使用抽象類,如果要在組件的所有實現間提供通用的已實現功能,則使用抽象類
4. 抽象類主要用於關系密切的對象,而接口適合為不相關的類提供通用功能
以下是我在網上看到的幾個形象比喻。
1.飛機會飛,鳥會飛,他們都繼承了同一個接口“飛”;但是F22屬於飛機抽象類,鴿子屬於鳥抽象類;
2. 就像鐵門木門都是門(抽象類),你想要個門我給不了(不能實例化),但我可以給你個具體的鐵門或木門(多態);而且只能是門,你不能說它是窗(單繼承),一個門可以有鎖(接口)也可以有門鈴(多實現)。門(抽象類)定義了你是什麽,接口(鎖)規定了你能做什麽(一個接口最好只能做一件事,你不能要求鎖也能發出聲音吧(接口汙染))。
靜態類:
靜態類不能被實例化,我們直接使用它的屬性與方法,靜態類最大的特點就是共享
1. 靜態類中的成員必須是靜態的
2. 靜態類可以有靜態靜態構造函數,靜態構造函數不可繼承
3. 靜態構造函數可以用於靜態類,也可以 用於非靜態類
4. 靜態構造函數無訪問修飾符、無參數,只有一個static標誌
5. 靜態構造 函數不可被直接調用,當創造類實例或引用任何靜態成員之前,靜態構造函數被自動執行,並且只執行一次
結構
-
沒有默認的構造函數,但是可以添加構造函數
-
沒有析構函數
-
沒有 abstract 和 sealed(因為不能繼承)
-
不能有 protected 修飾符
-
可以不使用 new 初始化
-
在結構中初始化實例字段是錯誤的
類
-
有默認的構造函數
-
有析構函數
-
可以使用 abstract 和 sealed
-
有 protected 修飾符
-
必須使用 new 初始化
相同之處:
-
結構和類對於程序來講都通過指針操作,同樣是面向對象的形式。
不同之處:
-
結構體對象總是在線程堆棧上操作,而不是托管堆上。
-
不能繼承一個結構體(所以在調用結構體的方法時不需要查找 vtable: 虛函數繼承表)
-
我們不能聲明構造函數為空的結構體(不曉得為啥非得要這麽設計)
-
結構體的構造函數內必須初始化所有變量(不曉得為啥非得要這麽設計)
-
結構體的字段不能有默認值(默認都是二進制意義上的零值),但是可以在構造函數內改變“默認值”
虛函數:
ref 和 out 的區別:
首先:兩者都是按地址傳遞的,使用後都將改變原來參數的數值。
其次:ref可以把參數的數值傳遞進函數,但是out是要把參數清空,就是說你無法把一個數值從out傳遞進去的,out進去後,參數的數值為空,所以你必須初始化一次。這個就是兩個的區別,或者說就像有的網友說的,ref是有進有出,out是只出不進。
盡管 ref 和 out 在運行時的處理方式不同,但在編譯時的處理方式相同。因此,如果一個方法采用 ref 參數,而另一個方法采用 out 參數,則無法重載這兩個方法。
如果一個方法采用 ref 或 out 參數,而另一個方法不采用這兩個參數,則可以進行重載,
1.給定三邊判斷三角形 2.字符串翻轉 3.修飾符 4.接口和抽象類 5.委托和事件 6.什麽情況下使用接口,什麽情況使用抽象類 7.對面向對象的理解
8.linq
9.虛方法和抽象方法
c# 曾經面試題