我說會C#,實際都是皮毛。買了《C#入門經典》(v6)和《C#高級編程》(v9),決定系統地學一遍。這是我的讀書筆記而已,不是什麼教程,如果有錯誤,還請各路大神指正。
希望自己堅持看完這兩本書,做好筆記,補缺補漏。
Framework 框架
Compact 精簡的
OOP(Object-Oriented Programming,面向對象編程)
CTS(Common Type System,通用類型系統)指如int等最基礎的數據類型
CLR(Common Language Runtime,公共語言運行庫)負責管理用.Net庫開發的所有程序的執行
CIL(Common Intermediate Language,通用中間語言)
JIT(Just-In-Time,准時、實時、即時)
GAC(Global Assembly Cache,全局程序集高速緩存)
WPF(Windows Presentation Foundation,Windows呈現基礎,取代原來的Windows Form)
WCF(Windows Communication Foundation,Windows通訊平台)
ASP.NET Active Server Pages.NET
ADO.NET Active Data Object.NET
IDE(Integrated Development Environment,集成開發環境)
概念
托管代碼 類型安全
Console Application 控制台應用程序
unsigned 無符號
#region 代碼塊(可折疊)
#endregion
@逐字指定字符,除雙引號外。
基礎類型中,string是引用類型,可指定null,其他類型為值類型。
數學運算符 - 取反,+ 不變。
int i = -3;
k = +i;//k=-3
k = -i;//k=3
++運算符放在操作數前面時,操作數在任何其他表達式計算前受到影響,而++運算符放在操作數後面時,操作數在完成表達式計算後才受到++運算符影響。例子見P36。
int i = 3, j = 3,k=0;
k = i++;//k=3
k = ++j;//k=4
為命名空間取別名。
using SL = System.Linq;
邏輯運算符 && || 與 & | 功能一樣,但推薦使用前者(性能較高)。
int i = 0;
bool a = (i != 0) && (2 / i > 0);//i為0時,不計算(2 / i > 0)
bool b = (i != 0) & (2 / i > 0);//i為0時,仍計算(2 / i > 0),引發除0錯誤
goto語句有用但最好不用。
int i = 5;
goto lable2;
i++;//未執行
lable2:
i--;//i為4
IntelliSense 智能感知
JaggedArray 鋸齒數組
char存儲的是數值,所以char被當做個數值類型。
checked/unchecked 用於類型轉換時,表達式的溢出檢查。(不檢查時,出現溢出則數據丟失)。
int i = 10000;
byte k = checked((byte)i);
enum 定義枚舉,詳見P81。
enum Day:short//默認基礎類型是int
{
Monday=1,//默認從0開始
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
數組定義,詳見P88。
//一維數組
const int constSize = 5;
int[] array1 = { 1, 2, 3, 4, 5 };//合法,數組默認值{ 1, 2, 3, 4, 5 }
int[] array2 = new int[constSize];//合法,數組默認值為int的默認值0
int[] array3 = new int[constSize] { 1, 2, 3, 4, 5 };//合法,數組默認值{ 1, 2, 3, 4, 5 }
int size = 5;
int[] array4 = new int[size];//合法,數組默認值為int的默認值0
int[] array5 = new int[size] { 1, 2, 3, 4, 5 };//【非法】,此處size應使用常量值(因為已初始化元素)
//矩形數組(每行的元素個數相同)
int[,] array6 = new int[3, 4];//二維數組,3行4列
int[, , ,] array7 = new int[1, 2, 3, 4];//多維數組
//鋸齒數組(數組的數組,每行的元素個數可能不同)
int[][] array8 = new int[][]
{
new int[]{1},
new int[]{1,2},
new int[]{1,2,3}
};
foreach循環與for循環的主要區別:foreach循環只可只讀訪問數組元素,而不能修改。
以下標方式訪問string的字符時,可讀不可寫。
string s = "abc";
char c = s[1];//合法,c='b'
s[1] = 'j';//非法,s[1]只讀
string.PadLeft() 用於字符串對齊。
string s = "abc",a,b;
a = s.PadLeft(10);//在s左部填充空格以達到長度10
b = s.PadLeft(10,'-');//在s左部填充'-'以達到長度10
parameter 形式參數(函數定義的一部分)
argument 實際參數(調用代碼傳遞給函數的參數)
參數數組,用params關鍵字為函數指定一個(只能一個)特殊參數,該參數只能是函數定義的最後一個參數。
static int Sum(params int[] nums)//params參數數組必須是參數定義中的最後一個參數
{
int sum = 0;
foreach (int n in nums)
{
sum += n;
}
return sum;
}
//使用
int sum=Sum(1,2,3,4);//可以指定任意多個int參數
ref參數:用作ref參數(引用參數)的變量有兩個限制:已初始化過的非const變量。
out參數:用作out參數(輸出參數)的變量可以是未賦值的變量。在函數使用out參數時,應將其看做是尚未賦值的變量。詳見P113。
函數簽名:函數名+參數。(唯一標志)
函數重載:函數名相同,但函數簽名不同。
Main()函數與命令行參數的使用。詳見P120。
delegate委托。委托是定義一個函數的類型(指定參數和返回類型),之後可將匹配該類型的函數作為該類型的變量來使用。詳見124。
delegate double MyDelegate(int a, int b);//聲明委托,指定參數與返回類型
double Multiply(int x, int y) { return x * y; }//與委托匹配的函數1
double Divide(int x, int y) { return x / y; }//與委托匹配的函數2
//使用
MyDelegate d;
double result;
d = new MyDelegate(Multiply);//實例化委托,此時d實際上就是函數Multiply
result = d(1, 2);// 1*2
d = new MyDelegate(Divide);//實例化委托,此時d實際上就是函數Divide
result = d(1, 2);// 1/2
Toggle BreakPoint 插入斷點 (Toggle 開關)
SEH(Structured Exception Handling,結構化異常處理)
非中斷模式調試:診斷輸出(C#功能,Debug.WriteLine()+Trace.WriteLine())+ 跟蹤點(VS功能)
中斷模式調試:配置斷點(斷點可以配置幾種中斷條件)+ Debug.Assert()
Debug.WriteLine() 只能用於調試模式(Debug),將文本寫到Output輸出窗口。
Trace.WriteLine() 可用於調試+發布模式(Release),將文本寫到Output輸出窗口。
System.Diagnostics.Debug.WriteLine("a debug message");//僅在調試模式起作用
System.Diagnostics.Trace.WriteLine("a trace message");//在調試+發布模式均起作用
UML(Unified Modeling Language,統一建模語言)
IDisposable接口與using關鍵字釋放資源。P162。
基類(父類)派生出派生類(子類),派生類繼承基類。
seal 密封類,不能用作基類,所以沒有派生類。
基類的成員可虛擬(virtual),由派生類重寫(override)實現。
abstract 抽象類,不能直接實例化,需被繼承。抽象類有抽象成員(需被重寫)和非抽象成員(有具體實現)。
interface接口,用於定義通用功能,不可自己實現。
abstract class(抽象類)與interface(接口):
在語法、用法上十分相近,但本質上不同:
抽象類:共性對象(強調屬性,是對有相似屬性的對象的概括,主要用作對象系列的基類)
接 口:相同功能(強調功能,完全不同的類也可以具有相同的功能)
virtual與abstract:詳見P193。
均用於基類中指定成員可被派生類用override關鍵字重寫,區別是:
virtual修飾的方法必須有方法體(實現),abstract修飾的方法不能有方法體(聲明);
virtual可以被派生類重寫或不重寫,abstract必須被重寫;
只有抽象類才可使用abstract修飾方法;
finalize 完成;結束
DLL(Dynamic Link Library,動態鏈接庫,又稱“應用程序拓展”)
class類、interface接口;幾種修飾關鍵字:internal (程序集內部訪問)/ public、abstract / sealed
類型比較object.GetType() == typeof(Object)。P181。
無參數構造函數為默認構造函數。
定義的類如果沒有使用基類,則只繼承於基類System.Object(C#中別名object)。實例化派生類時,基類調用其默認構造函數。因此,實例化一個類時,總是首先調用System.Object.Object()。
值類型與引用類型:值類型(簡單類型+結構體struct),引用類型(string+類class),詳見P195。
關於對象復制,詳見P197+P254。
shallow copy 淺度復制:System.Object的MemberwiseClone(),對引用類型對象復制的是引用。
deep copy 深度復制:實現ICloneable接口的Clone()方法,詳見P254。
refactoring 重構
implementation 實現
readonly關鍵字:表明字段只能由構造函數或初始化賦值語句進行賦值。
const成員也是靜態的,所以不需要static修飾。
字段與屬性的區別:
//私有字段,camelCasing
private int number;//字段
//公共字段,PascalCasing
public string Name;//字段
public int Number//屬性
{
get { return number; }
protected set //可為訪問器設置訪問性
{
//屬性控制
if (value > 0)
{
number = value;
}
else
{
//拋出異常提供控制權
throw new ArgumentOutOfRangeException("Number", value, "Number 必須大於0");
}
}
}
自動屬性:由編譯器聲明對應私有字段
public int Number { get; protected set; }
隱藏基類方法:派生類繼承方法前加關鍵字new。
接口的實現。P217。(隱式、顯式實現區別,特殊屬性訪問器)
capacity 容量
indexer 索引符
boxing 封箱/裝箱
unboxing 拆箱
operator overloading 運算符重載
implicit / explicit 隱式/顯式
CollectionBase、DictionaryBase:自定義集合類可繼承這兩個類,詳見P242。
yield關鍵字:在迭代器塊中選擇在foreach循環中使用的值。
封箱/裝箱:封箱可以看作是淺度復制的過程,值類型封箱引用新副本,引用類型封箱引用源引用類型。
is運算符:用於檢查對象是否可以轉換為指定類型(基類或接口),可以轉換運算符返回true。
classa.GetType()== typeof(ClassA):用於檢查對象是否就是指定類型。
as運算符:用於把一種類型轉換為指定的引用類型。以下兩句代碼等價,但有不同,詳見P279。
return cards.Clone() as Cards;
return (Cards)cards.Clone();
運算符重載:P264
//運算符重載
public static bool operator ==(Card c1, Card c2)
{
return (c1.suit == c2.suit) && (c1.rank == c2.rank);
}
public static bool operator !=(Card c1, Card c2)
{
return !(c1==c2);//調用其他運算符減少代碼量和錯誤可能
}
//重寫該方法可以確保任何比較技術得到的結果相同
public override bool Equals(object obj)
{
return this == (Card)obj;//具體比較操作
}
//重寫該方法可以確保任何比較技術得到的結果相同
public override int GetHashCode()
{
return 13 * (int)suit + (int)rank;//根據狀態,返回對象實例的唯一int值
}
IComparable接口:在要比較對象的類中實現CompareTo(),比較對象與對象,如:a.CompareTo(b)
IComparer接口:在單獨的比較類(比較器)中實現Compare(),如:comparer.Compare(a,b)
arrayList.Sort():使用項的CompareTo()進行默認排序,或傳入一個比較器(實現IComparer接口的類)實例進行自定義排序,如arrayList.Sort(comparer)。詳見P274。
implicit / explicit 關鍵字:用於指定隱式/顯式類型轉換,詳見P279。
public static explicit operator ClassA(Class2 obj)
{
ClassA returnObj = new ClassA();
checked { returnObj.val = obj.val; }//在顯式轉換中建議使用checked檢查溢出
return returnObj;
}
generic 通用的;一般的
N/A(Not Applicable,不適用(不是Not Available))
predicate 斷言;判定
System.Nullable:可空類型,用於使值類型為空null。
//以下兩句代碼等價
System.Nullable nullableInt1 = null;
int? nullableInt2 = null;
??運算符:可用於為可空類型提供默認值,不需要使用if判斷。
op1 ?? op2 //等價於下句
op1 != null ? op1 : op2 //當op1非空時返回op,1,否則返回op2
泛型元素:類、方法、接口、委托,如:
List、Dictionary//泛型類
IComparer、IComparable//泛型接口
Comparison、Predicate//泛型委托
...//泛型方法
default關鍵字:定義泛型類中根據T是值類型/引用類型賦予值類型默認值/null。
where關鍵字:約束可用於實例化泛型類的類型。
協變關鍵字out:協變類型參數只能用作返回值或者屬性get訪問器(輸出)。
抗變關鍵字in:抗變類型參數只能用作方法參數,不能用作返回類型(輸入)。
alias 別名
nest 嵌套;巢
subscribe 訂閱
:: 運算符:當命名空間的別名與實際存在的命名空間重名時,編譯器默認使用實際命名空間,此時可使用::符號迫使編譯器使用由using語句定義的別名。
global關鍵字:實際是頂級根名稱空間的別名。
定制異常:繼承基類Exception,用try{…}catch{…}finally{…}捕獲。
event關鍵字:定義事件
//Step0.定義參數類型(必要時),繼承EventArgs
public class MyEventArgs : EventArgs
{
private string message;
public string Message { get; set; }
public MyEventArgs(string msg) { message = msg; }
}
//Step1.定義委托,指定事件處理方法的參數和返回類型
//(標准事件委托:void返回類型+object事件源+繼承EventArgs的事件參數)
public delegate void MyEventHandler(object sender, MyEventArgs e);
//Step2.定義事件,並指定要使用的委托類型。
public event MyEventHandler LastCardDrawn;
//觸發事件
public Card GetCard(int cardNum)
{
//當事件為null時說明該事件沒有訂閱者,不會引發事件
if (cardNum == 51 && LastCardDrawn != null)
LastCardDrawn(this, new MyEventArgs("自定義參數"));//觸發事件,傳遞事件參數
return cards[cardNum];
}
事件處理程序最好使用void返回類型;有返回值時(非void),訪問的是最後一個訂閱事件的處理程序返回值。
EventHandler、EventHandler:.NET定義的委托類型,使用標准的事件處理模式,其原型為:
public delegate void EventHandler(object sender, EventArgs e);
public delegate void EventHandler(object sender, TEventArgs e);
匿名方法:使用delegate關鍵字就地定義一個純粹用作委托目的的處理程序,詳見P335。
Attribute特性:對代碼進行裝飾,如[DebuggerStepThrough],通過反射讀取特性值,詳見P344。
還沒看,待續…