標籤:c# 陳小道 學習筆記
筆記來自《C#圖解教程》
每個.cs檔案至少需要包含一個和檔案名稱相同的類
解構函式:執行在類的執行個體被銷毀之前需要的清理或釋放非託管資料的行為。
每個類只能有一個解構函式;
不能帶參數;
不能帶存取修飾詞。
虛方法/覆寫方法(需要在衍生類別中重寫基類的某些方法時)
virtual/override
存取修飾詞:
public完全公開
private類內部(預設)
protected同一名字空間內的衍生類別可以訪問
internal同一名字空間內的任何地方可以訪問
protected internal或
抽象成員:abstract
不能virtual abstract
抽象的實現必須override
密封類(sealed):只能用作獨立的類,不能被用作基類。
靜態類:所有成員都標記static;不能繼承,不能建立執行個體;
擴充方法:public static double Average(this MyData.md)
外部方法:在聲明中沒有實現的,其實現往往是用C#之外的語言編寫的。
public static extern int func(int size, stringBuilder buf);
字串:規格/逐字(以@為首碼)
左移相當於乘2的n次方;右移相當於乘2的-n次方;
使用者自訂類型轉換:
隱式轉換:implicit
顯式轉換:explicit
運算子多載:
public static LimitedInt operator +(LimitedInt x, double y){}
typeof運算子:
Type t = typeof(SomeClass);
GetType/ToString/Equals/GetHashCode
數字在C#中沒有布爾意義。
using別名指令:
using Syst = System;
using sc = System.Console;
catch子句:
catch{}
catch(Type){}
catch(Type instID){}
拋出異常:throw ExceptionObject;
結構
類是參考型別而結構是值類型;
結構是隱式密封的,不能被派生;
結構複製,從一個結構中把值複製到另一個結構,複製類變數時只有引用被複製。
預定義的無參數建構函式對每個結構都存在,而且不能刪除或重定義方法。
不能new建立struct,不能使用資料成員的值直到顯式設定它。
欄位初始化是不允許的。
分配結構比建立類的執行個體需要更少的消耗。
枚舉enum TrafficLight : long
{
Green = 10,
Yellow, //值為11
Red //值為12
}
值類型:只有一種類型的成員,命名的整數值常量;
每個枚舉類型都是一個底層整數類型,預設為int。
數組(參考型別):一旦建立,大小固定,C#不支援動態數組。
從System.Array繼承的對象
Rank維度
Length元素個數
int[] intArr = new int[]{10, 20};
foreach(int item in arr){}
數組協變:即使某個對象不是數組的基底類型,我們也可以把它賦值給數組元素。
數組是參考型別數組。
clone方法:
複製值類型數組會產生兩個獨立數組;
複製參考型別數組會產生指向相同對象的兩個數組。
列表
列表比數組更常用,因為列表更靈活。
聲明列表的格式如下:
List<datatype> <var name> = new List<datatype>();
List<int> intList = new List<int>();
其他資料結構:隊列、字典 (雜湊表的實現)、雜湊集合、唯讀集合、元組 (.Net 4+)
委託包含具有相同簽名和返回值類型的有序方法(執行個體/靜態)列表的對象。
當委託被調用時,它調用列表中的每一個方法。
委託是物件導向的,而且是型別安全的。
委託和類一樣,是一種類型。必須在被用來建立變數以及類型之前聲明。
delegate void MyDel(int x);
傳回型別和簽名指定了委託接受的方法的形式。
委託聲明與方法聲明不同在於:以delegate關鍵字開頭;沒有方法主體。
MyDel devVar = new MyDel(myInstObj.MyM1);//建立委託並儲存引用
或 MyDel devVar = myInstObj.MyM1;//在方法名稱和其委託類型之間有隱式轉換
MyDel delA = myInstObj.MyM1;
MyDel delB = SClass.OtherM2;
MyDel delC = delA + delB; //組合調用列表
委託是恒定的,委派物件被建立後不會再被改變。
MyDel delVar = inst.MyM1;//建立並初始化
delVar += SCl.M3;//增加方法
delVar -= SCl.M3;//移除方法
如果調用列表為空白,則委託是null;
試圖調用空委託會拋出異常;
試圖刪除委託中不存在的方法沒有效果;
-=移除第一個匹配的執行個體;
delVar(55);//調用委託
調用帶返回值的委託,最後一個方法返回的值就是委託調用返回的值。其他方法返回值都會被忽略。
調用帶引用(ref)參數的委託,參數值會根據調用列表中的一個或多個方法的返回值而改變。在調用委託列表中的下一個方法時,參數的新值(不是初始值)會傳給下一個方法。
匿名方法,是在初始化委託時內聯聲明的方法。
OtherDel del = delegate(int x){ return x + 20; };
不能顯式聲明返回值,但是在實現代碼本身的行為必須通過返回一個在類型上與委託的傳回型別相同的值來匹配委託的傳回型別。
如果委託聲明的參數列表包含了params參數,那麼params關鍵字就會被匿名方法的參數列表忽略。
Lambda運算式
MyDel del = delegate(int x) { return x + 1; };//匿名方法
MyDel lel1 = (int x) => { return x + 1; };//運算式
MyDel lel2 = (x) => { return x + 1; };//運算式
MyDel lel3 = x => { return x + 1; };//運算式
MyDel lel4 = x => x + 1;//運算式
事件事件其實就好像被簡化的針對特殊用途的委託。註冊到事件上的方法會在事件觸發時被調用。
觸發事件:調用(invoke)或觸發事件的術語。當事件被觸發時,所有註冊到它的方法都會被依次調用。
發行者(publisher):讓事件被其他類或結構可見並使用的類或結構。
訂閱者(subscriber):把事件和發行者關聯註冊的類或結構。
事件處理常式(event handler):註冊到事件的方法。可以在事件所在的類或結構中,或者在不同的類或結構中。
事件包含一個私人委託。
聲明事件
public event EventHandler Elapsed;
事件是成員不是類型。隱式自動初始化為null。
public event EventHandler Elapsed;
private void OnOneSecond(object source, EventArgs args)
{
if (Elapsed != null)
{
Elapsed(source, args);
}
}
發行者類有一個作為成員的事件。
類包含了觸發事件的代碼。
標準事件的用法
public delegate void EventHandler(object sender, EventArgs e);
為了向自己的事件處理常式的第二個參數傳入資料,並且又符合標準慣例,需要聲明一個派生自EventArgs的自訂類。
使用自訂委託
public delegate void MyTCEventHandler(object sender, MyTCEventArgs e);
public event EventHandler<MyTCEventArgs> Elapsed;
System.Timers.Timer的Interval屬性,指定觸發事件間隔的毫秒數。
+=和-=運算子是事件允許的唯一運算子。這些運算子有預定義行為,我們可以修改這些運算子的行為。通過事件訪問器來實現。
public event EventHandler Elapsed
{
add{...}
remove{...}
}
介面介面是表示一組函數成員而不實現成員的參考型別。類和結構可以實現介面。
public interface Icomparable
{
int CompareTo(object obj);
}
介面聲明可以有任何的存取修飾詞;但是介面的成員是隱式public的,不允許顯式。
如果類從基類繼承並實現介面,基類列表中的基類名稱必須放在任何介面之前。
class Derived : MyBaseClass, IEnumerable, IEnumerator{}
不能直接通過類對象的成員提供者。可以通過把類對象引用強制轉換為介面類型來擷取指向介面的引用。有了介面的引用,就可以使用點號來調用介面的方法。
as運算子
IliveBirth b = a as IliveBirth;
如果實現了介面,返回指向介面的引用;
如果沒有實現介面,返回null。
如果一個類實現了多個介面,那麼其中一些介面有相同簽名和傳回型別的成員。類可以實現單個成員來滿足所有包含重複成員的介面。
實現介面的類可以從它的基類繼承實現的代碼。
顯式介面成員實現,使用限定介面名稱來聲明,由介面名稱和成員名稱以及它們中間的點分隔字元號構成。必須總是通過介面的引用來訪問。
介面也可以繼承自一個或多個介面。類只能繼承一個父類。
轉換對於有符號類型的轉換而言,額外的高位用源運算式的符號位進行填充。
裝箱:轉換任何值類型到object類型/System.ValueType類型;
拆箱:轉換裝箱的值到原始類型。
溢出檢測上下文,如果丟失會拋出OverflowException異常
運算子:
checked(運算式)
unchecked(運算式)
語句:(可以嵌套)
unchecked
{
...
checked
{
...
}
}
知道發生資料丟失時轉換會如何處理很重要。
double到整數:如果結果值不在目標類型的範圍內,則拋出OverflowException;
double到float:如果太小而不能用float表示,那麼值設定為正或負0;如果太大,而不能用float表示,則會被設定為正或負無窮大。
float或double到decimal:值太大而不能用decimal表示,那麼設定為0;如果太大,拋出OverflowException異常。
decimal到float或double:總是成功,但是有可能會損失精度。
父類強制轉換成子類會導致InvalidCastException異常,但不是編譯錯誤。
有效顯式引用轉換
1、從衍生類到基類的轉換;
2、源引用是null;
3、由源引用指向的實際資料可以被安全地進行隱式轉換。
裝箱轉換
是一種接受值類型的值,根據這個值在堆上建立一個完整的參考型別對象並返回對象引用的隱式轉換。
int i = 12;
object o = null;
o = i;
在記憶體中建立int類型對象;
複製i的值到這個對象;
把int對象的引用返回給i;
任何值類型ValueTypes都可以隱式轉換為object、System.ValueType或InterfaceT(如果ValueTypeS實現了InterfaceT)。
拆箱轉換
是把裝箱後的對象轉換回值類型的過程。
嘗試拆箱一個值為非原始類型時會拋出一個InvalidCastException異常。
使用者自訂轉換:除了標準轉換,我們還可以為類和結構定義隱式和顯式轉換。
public static implicit operator TargetType(SourceType Identifier)
{
...
return ObjectOfTargetType;
}
將Person轉換為int
public static implicit operator int(Person p)
{
return p.Age;
}
is運算子
Expr is TargetType; //返回bool
如果Expr運算式可以通過以下方式被成功轉換為目標類型,運算子返回true。
引用轉換、裝箱轉換、拆箱轉換。不能用於使用者自訂轉換。
as運算子
和強制類型轉換運算類似,只是它不拋出異常。如果轉換失敗,它把目標引用設定為null而不是拋出異常。
Expr as TargetType;
Expr源運算式;TargetType目標類型,必須是參考型別;
只能用於引用轉換和裝箱轉換,不能用於使用者自訂轉換或到值類型的轉換。
泛型泛型允許我們宣告類型參數化的代碼,我們可以用不同的類型進行執行個體化。也就是說,我們可以用“類型預留位置”來寫代碼,然後在建立類的執行個體時提供真實的類型。
泛型聲明執行個體:
class MyStack <T>
{
int StackPointer = 0;
T [] StackArray;
public void Push(T x) {....}
public T Pop(){...}
}
T代表類型的預留位置,也不一定要是字母T,可以是任何標識符。T又稱為型別參數。
class SomeClass <T1, T2>
{
public T1 SomeVar = new T1();
public T2 OtherVar = new T2();
}
SomeClass<short, int> myInst;
myInst = new SomeClass<short, int>();
var mySc = new SomeClass<short, int>();
用var關鍵詞使編譯器使用類型引用;
只有符合約束的實參才能用於型別參數。通過where子句來實現約束。
class MyClass <T1, T2, T3>
where T2 : Customer
where T3 : IComparable
{...}
5種類型約束:
類名:只有這個類型的類或從它繼承的類才能用作類型實參;
class:任何參考型別,包括類、數組、委託和介面都可以用作實參;
struct:任何值類型都可以被用作類型實參;
Interfacename:只有這個介面或實現這個介面的類型才能用作實參;
new():任何帶有無參公用建構函式的類型都可以用作實參,這叫做建構函式約束。
泛型結構:
struct PieceOfData<T>
{
public PieceOfData(T value) {_Data = value; }
private T _Data;
public T Data
{
get { return _Data; }
set { _Data = value; }
}
}
泛型介面:
interface IMyIfc<T>
{
T ReturnIt(T inValue);
}
class Simple<S> : IMyIfc<S>
{
public S ReturnIt(S inValue)
{
return inValue;
}
}
class Simple2 : IMyIfc<int>, IMyIfc<string>
{
public int ReturnIt(int inValue)
{ return inValue; }
public string ReturnIt(string inValue)
{ return inValue; }
}
實現泛型型別介面時,必須沒有可能的類型實參組合會在類型中產生兩個重複的介面。
泛型委派:
delegate R MyDelegate<T, R>(T value);
delegete void MyDelegate<T>(T value);
var myDel = new MyDelegate<string>(Simple.PrintString);
泛型方法:
public void PrintData<S, T>(S p) where S: Person{...}
泛型類的擴充方法:
必須聲明為static;
必須是靜態類的成員;
第一個參數類型中必須有關鍵字this,後面是擴充的泛型類的名字;
public static void Print<T>(this Holder<T> h){...}
枚舉數和迭代器數組可以按需提供一個叫枚舉數的對象。枚舉數可以依次返回請求的數組的元素。枚舉數“知道”項的次序並且跟蹤它在序列中的位置,然後返回請求的當前項。
可枚舉類型實現GetEnumerator方法。
實現枚舉數的方式:
IEnumerator/IEnumerable介面;
IEnumerator<T>/IEnumerable<T>介面;
不使用介面形式;
IEnumerator介面包含三個方法:Current、MoveNext和Reset
IEnumerable介面只有一個方法:GetEnumerator,它返回對象的枚舉數。
迭代器
迭代器塊是有一個或多個yield語句的代碼塊。迭代器塊中的代碼描述了如何枚舉元素。
yield return執行了序列中返回的下一項;
yield break指定在序列中沒有更多項;
public IEnumerator<string> BlackAndWhite()
{
yield return "black";
yield return "gray";
yield return "white";
}
LINQ用於提供查詢資料能力的一個新特性。
LINQ(發音為link)代表Language-integrated Query (LINQ)(Language Integrated Query);
LINQ是.NET架構的擴充,它允許我們以資料庫查詢的方式查詢資料集合;
C# 3.0包含集合LINQ到語言中的一些擴充,允許我們從資料庫、程式對象集合以及XML文檔中查詢資料。
匿名型別:
var student = new {LName="Jones", FName="Mary", Age=19, Major="History"};
var student = new { Age=19, Major, Other.Name };
賦值形式;標識符形式;成員存取運算式;
方法語句:
int[] numbers = {2, 5, 28, 31};
var numsMethod = numbers.Where(x => x < 20);
int[] arr1 = {10, 11, 12, 13};
var query = from item in arr1
where item < 13
select item;
int[] numbers = { 2, 12, 5, 15 };
IEnumerable<int> LowNums = from n in numbers
where n < 10
select n;
join子句
var query = from s in students
join c in studentsInCourses on s.StID equals c.StID;
from子句
var groupA = new[]{3, 4, 5, 6};
var groupB = new[]{6, 7, 8, 9};
var someInts = from a in groupA
from b in groupB
where a > 4 && b <= 8
select new {a, b, sum = a + b };
let子句:接受一個運算式的運算並且把它賦值給一個需要在其他運算中使用的標識符;
var someInts = from a in groupA
from b in groupB
let sum = a + b
where sum == 12
select new {a, b, sum };
where子句可以多個;
orderby子句:接受一個運算式並根據運算式依次返回結果項,可以多個用逗號隔開;
預設升序,升序關鍵字ascending,降序關鍵字descending;
group子句:
var query = form student in students
group student by student.Major;
作為分組依據的項叫做鍵key。
查詢延續:
var someInts = from a in groupA
from b in groupB on a equals b
into groupAandB
from c in groupAandB
select c;
XML類
最重要的類包括:XElement、XAttribute和XDocument
XDocument employees1 =
new XDocument(
new XElement("Employees",
new XElement("Name", "Bob Smith"),
new XElement("Name", "Sally Jones")
)
);
employees1.Save("EmployeesFile.xml");
XDocument employees2 = XDocument.Load("EmployeesFile.xml");
Console.WriteLine(employees2);
EmployeesFile.xml內容:
<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Name>Bob Smith</Name>
<Name>Sally Jones</Name>
</Employees>
查詢XML的方法:
Nodes
Elements
Element
Descendants
DescendantsAndSelf
Ancestors
AncestorsAndSelf
Parent
增加/刪除節點以及操作XML:Add()、AddFirst、AddBeforeSelf、AddAfterSelf、Remove、RemoveNodes
使用XML屬性:屬性提供了有關XElement節點的額外資訊,它放在XML元素的開始標籤中。
new XAttribute("color", "red");
<root color="red">
</root>
節點的其他類型:XComment、XDeclaration以及XProcessingInstruction
使用LINQ to XML的LINQ查詢:
XDocument xd = XDocument.Load("SimpleSample.xml");
XElement rt = xd.Element("MyElements");
var xyz = from e in rt.Elements()
where e.Name.toString().Length == 5
select e;
非同步編程簡介當我們啟動一個程式時,系統在記憶體中建立一個新的進程。進程就是一組資源,它們構成了一個正在啟動並執行程式。這些資源套件括虛擬位址空間、檔案控制代碼以及程式啟動需要的其他東西的載體。
如果委派物件在調用列表中只有一個方法(之後會叫做引用方法),它就可以非同步執行這個方法。委託類有兩個方法,叫做BeginInvoke和EndInvoke。它們就是用來這麼做的。
預先處理指令原始碼指定了程式的定義。預先處理指令指示編譯器如何處理原始碼。
#define identifier
#undef identifier
#if expression
#elif expression
#else
#endif
#region name
#endregion name
#warning message
#error message
#line indicator
#pragma text
例子:
#define DEBUG
...
#if DEBUG
//這裡的代碼會被執行
#else
//這裡不會執行
#endif
反射和特性有關程式及其類型的資料被稱作中繼資料,它們儲存在程式的程式集中;
程式在運行時,可以查看其它程式集或其本身的中繼資料。一個啟動並執行程式查看本身的中繼資料或其他程式的中繼資料的行為叫做反射。
Type類成員:Name、Namespace、GetFields、GetProperties、GetMethods
擷取Type對象:
Type t = myInstance.GetType();
Type t = typeof(DerivedClass);
特性是一種允許我們向程式的程式集增加中繼資料的語言結構。
特性的目的是告訴編譯器把程式結構的某組中繼資料嵌入程式集。
[ Serializable ]
public class MyClass
{...}
[ MyAttribute("Simple class", "Version 3.57") ]
public class MyOtherClass
{...}
預定義特性:CLSCompliant Serializable NonSerialized Obsolete DLLImport WebMethod AttributeUsage
全域特性:用assembly和module來使用明確顯示目標把特性設定在程式集或模組層級別。
程式級層級的特性必須放置在任何命名空間之外,並且通常放置在AssemblyInfo.cs檔案中;
AssemblyInfo.cs檔案通常包含有關公司、產品以及著作權資訊的中繼資料。
自訂特性
public sealed class MyAttributeAttribute : System.Attribute
{...}
每個特性至少必須有一個公用建構函式。
用Type的IsDefined方法檢測某個特性是否應用到了某個類上。
使用GetCustomAttributes方法返回應用到結構的特性的數組。
其他主題string和StringBuilder
格式化數字字串:
Console.WriteLine("The Value: {0:C}.", 500 );//格式化貨幣
Console.WriteLine("The Value: {0,10}.", 500 );//在10字元的欄位中靠右對齊
標準數字格式化說明符;
把字串解析為數字值:double d = double.Parse("25.873");另一個方法TryParse,如果解析失敗,返回false。
可空類型:建立一個值類型的變數並標註它為有效或無效。
int? myNInt = 28;
if( myNInt != null ) {...}
可空類型通過一個叫做System.Nullable<T>的.NET類型來實現。
Main方法
static void Main{...}
static void Main(string[] args){...}
static int Main(){...}
static int Main(string[] args){...}//成功返回0
可以聲明為public和private
/// 表示文檔注釋
巢狀型別
class MyClass
{
classMyCounter
{...}
...
}
文檔資訊
- 著作權聲明:自由轉載-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
- 原文網址:http://blog.csdn.net/cdztop/article/details/38644345