面向對象的三大特徵: 封裝性 繼承性 多態性程序員
一.繼承:類與類的關係編程
爲何會用繼承:減小代碼重複 優化 空間內存 實現多態 c#
class 基類 { //基類成員 } class 子類:基類 { //子類成員 }
判斷繼承關係 用進行進行判斷--》子類對象 is 父類成員安全
例如 諾基亞手機 諾基亞280 諾基亞板磚007 框架
繼承特徵 :1.單根性 一個只能繼承自一個類 不可能繼承倆個類 iphone
2.傳遞性 爺爺 父親 孫子 ide
3.派生於object根類(c#範圍) c#裏面的全部成員都來源於object 用於實現多態函數
注意: 1.繼承中構造函數的問題 其實就是執行順序優化
2.能夠手動添加一個無參構造方法this
3.訪問修飾符
繼承練習:
寫一個student類 姓名 性別 年齡 hello方法與teacher類 姓名 性別 年齡 工資 hello方法 經過構造方法爲成員賦初值 說hello
class student { private string _name; private string _age; private string _gender;//三個字段填充類的信息 public Student (string name ,int age ,char gender)//方法給三個字段賦值 –->4 {
_name=name; _age=age; _gender=gender; } public string Name { get{return _name;} } public int Age { get {return _age;} } public char Gender { get {return _gender} } //三個屬性限制訪問級別 爲了數據安全 }
class Teather : Student { private int _score; public Teacher(string name , int age ,char gender , int score): base (name ,age ,gender)—->3 -->5 { _score =score; } public void Hello() -->7 { Console.WriteLine("你們好,我叫{0},今年{1}歲了,我是{2}生,我此次考了{3}分",Name,Age,Gender,_Score); -->8 } public int Score { get {return _Score;} } } class Pregram { static void Main(string [ ] args ) { -->1 Teacher tea1= new Teacher ("張三 ",19,'男',95); -->2 -->6 stu1.Hello(); Console.ReadKey(); -->9 } }
解析代碼:
public Teacher(string name , int age ,char gender , int score)//定義子類構造方法
: base (name ,age ,gender) 調用父類方法 爲何不這樣寫 base (string name ,int age ,char gender) 由於name已經定義過了若是寫string name 有類型和變量 這就是定義 而不是傳參
base : 若是這裏你不用base調用父類構造方法爲子類賦初值,那你只有本身手動在子類構造方法裏面爲子類賦初值例子以下:
base._name-name; this._age=age; this.gender=gender;
注意:這裏的base和this沒區別 在字段前加base和this只要不會由編譯器誤解給程序走看的。
上面代碼涉及構造方法(繼承中)的執行順序:
1.調用子類構造方法時,先調用父類構造方法 這裏的base是在調用父類構造方法 base後面的參數 name,age,gender應該和4參數對應
2.private的限制 類裏面class{}大括號範圍
二.繼承中關於構造方法的調用this和base區別
this : 表示當前類 ,表示當前構造方法 --》解析:指定先調用哪個當前類的構造方法就一個類裏面(變化在一個類)
base:表示父類,父類構造方法--》解析:指定首先調用哪個父類構造方法(變化在子類和父類 倆個類或多個類)
構造方法不同你建立出來的對象就是不同
this代碼示例以下:
class Myclass { public Myclass -->4 { Initiallomporrent(); -->此爲標準的構造方法執行全部字段的初始化工做 } public Myclass (string n) : this () -->3 -->7 { Console.WriteLine(n); --》8 } --》9 private void IntialComent()......摺疊代碼 --》6 //此句是全部字段進行初始化 } class Program //先初始化窗體而後去擴展 { static void Main (string [ ] args ) { -->1 Myclass myclass=new MyClass("123"); -->2 -->10 } }
解析代碼:
2 3 4 7 8 調用帶有參數string n 這個構造方法以前 先去調用標準的構造方法
三 . 繼承構造方法《1》
問題:在建立對象的時候就是調用類的構造方法進行初始化 所以在建立對象時,父類構造方法有沒有被調用 怎麼證實?
構造方法:
public 類名() //保證此時的方法名就是類名 保持一致 { //方法體 }
此時:構造方法沒有返回值。能夠添加參數,因此也就能重載 構造方法不能直接調用 除非只能 new。
class BaseClass { } class Subclass:Baseclass { } clsaa Program { static void Main(string [ ] args ) { SubClass sub=new SubClass();
} }
注意:
1. 此時class baseclass 與 class subclass 中看不到方法 不表明沒有方法 若是此時你看到 那麼new subclass()調用clsaa baseclass 與 class subclass 中的默認無參構造方法
2. 若是有須要 你就得手動添加構造方法
下面代碼是證實過程:
證實:1. 如何看子類建立對象得時候,有沒有調用父類構造方法
2. 若是你在父類中輸出一句話,看到調用時打印這句話了沒有
class BaseClass { public BaseClass():base() --》5 //base做用 調用object 只是你看不到 { Console.WriteLine("我是父類"); --》6 } } class SubClass:BaseClass { public SubClass ():base() -->4 -->7 { Console.WriteLine("我是子類"); -->8 } } class SubSubClass: SubClass { public SubSubClass: base() --》3 --》9 { Console.WriteLine("我是孫子類"); --》10 } } class Program { static void Main( string [ ] args) -->1 { SubSubClass sub =new SubSubClass(); -->2 -->11 Console.ReadKey(); --》12 } }
解析代碼過程:
1. Main 方法開始執行
2.調用了建立對象得new SubSubclass()方法
2→3 跳到 SubSubclass()方法
3 執行了完成 可是沒有執行consolle.writeline (「我是子類」)緣由在於base 若是 此處沒寫base 系統也會默認這裏有base由於此處有了base 因此3直接→4而後到5 這裏的base做用是調用object 由於object 是全部成員得根類5→6 打印 我是父類 6→7按順序開始執行了 7→8 開始打印 我是子類 8→9→10→11 這裏的new subsubclass () 括號裏沒有參數 編譯器默認添加得無參構造函數 你也能夠手動添加 而後 →12 結束!
以上就是構造方法執行順序 base();
注意:
1.在建立對象得時候,好像是先調用父類構造方法,在調用子類構造方法從5開始得 1→4 實際上是先調用子類構造方法往上推到頂層在順序下來。
2.在調用構造方法的時候,其實默認有一個base(),調用了父類無參得構造方法好比 4調用5 public BaseClass ()這個父類無參構造方法。
//自定義調用構造方法順序 :默認是調用無參構造方法 可是你能夠指定調用它得那個有參構造方法 class BaseClass { public BaseClass():base() --》若是此時在 public BaseClass( int i )添加參數 { Console.WriteLine("我是父類"); } } class SubClass:BaseClass { public SubClass ():base() //這裏就會出錯 由於這裏調用默認的無參構造方法 { //此時有參數了 調不成 怎麼破?解決方法以下1和2 Console.WriteLine("我是子類"); } } class SubSubClass: SubClass { public SubSubClass: base() { Console.WriteLine("我是孫子類"); } } class Program { static void Main( string [ ] args) { SubSubClass sub =new SubSubClass(); Console.ReadKey(); } } 解決方法一 就是手動添加一個無參構造函數 public BaseClass() { Console.WriteLine("我是父類"); } 解決方法二 就是用base直接傳一個參數 可是裏面傳得參數必須和上面類型對應 上面是int型 因此這裏傳1 若是上面定義的是string 型 這裏傳 「1」 public SubSubClass: base(1) { Console.WriteLine("我是孫子類"); }
隱藏基類方法 :父類和子類方法名相同 (徹底相同得方法)
爲何要隱藏基類方法:由於只有這樣 子類對象就知道該如何控制它訪問本身得方法和父類得方法
代碼示例:
Class 老公 { public void Func ()------->1 { Console.WriteLine("體貼"); } } Class 父親:老公 { public void Func()-------->2 { Console.WriteLine('關愛'); } } Class Program { Static void Main ( string [ ] args) { Object o = new 父親(); o.Func(); ((父親)o).Func(); ((老公)o).Func(); } } 此時若是1和2這樣寫 會出現異常1和2方法同名 若是有意隱藏,請使用關鍵字new 2 寫成 public new void Func () 其實這裏的new給編譯器和程序員看的 不寫同樣
代碼解析:
若是子類方法例如 public void Func()與父類方法 public coid Func()相同 那麼調用時例如 o.Func()這時你調用誰?
很顯然調用的是class 父親中的 public void Func();由於當子類方法和父類方法同名時這時候就將調父類方法 例如 :
父類 class 老公 {public void Func () {}} 方法隱藏了 可是隻是隱藏 不是消失 若是父類方法隱藏了 能不能調用呢?
解釋:能調用 可是看類型 隱藏看類型 例如 ((父親)o).Func(); 此時是父親這個類型 ((老公)o).Func(); 此時類型是老公這個類型
里氏轉換概念: 若是一個類型 它有父類 也有子類 那麼子類的對象能夠直接賦值給個人父類 是 賦值 。
代碼示例 :
MyBase myBase = new MySub(); //new的一個子類對象 父類 子類 上面代碼等同下面代碼: MySub Sub= new MyBase(); MyBase mBase=Sub ; myBase.Func();
單例模式:
相似飛秋 一個電腦只能運行一個 可是QQ不同 你能夠登錄多個號碼
代碼示例:
Class Myclass { private static MyClsaa_default = null; -->1 //靜態字段 public static MyClass Default --》2 { get { if (_default = null) -->5 { _default = new MyClass(); return _default; } else { return _default; -->6 } } } } (public) private MyClass ()//當這裏的public 改爲 private 的時候 你建立對象調用方法時會出現問題 由於有了private 限制 那麼怎麼辦呢? { //解決辦法就是 建立一個靜態的字段 1 而後爲1 寫一個方法(或者屬性) 2 } Class Program { static void Main (string [] args ) { MyClass myClass = MyClass.Default; -->3 Myclass myClass2=MyClass.Default; -->4 } }
代碼解析:
1.當第一次運行3的時候 此時_default=null 因此執行 5 當運行4的時候 _default不等於 null 這時執行6 返回_default 其實就是第一次
重寫基類方法實現多態 (里氏轉換原則)
協議不是一個實實在在存在的東西,不該該能讓一個協議去作什麼事情或者作什麼東西 是咱們根據協議去作一些事情或者一些東西例如: USB協議 咱們能夠根據usb協議製做讓手機傳數據東西或者usb燈 讓燈發光等等
加入Virtual 表明是虛 前面加了virtual這個方法就是虛方法也有方法體也能夠調用例如: new Protoul ().usb();能夠打印說明能夠調用,爲何要加virtual在子類上 說明重寫了基類方法 public virtual void usb();
在只有一個usb接口就是一個對象調用usb();這樣一個方法根據這個usb()接口插上去這個東西是什麼作相應的反應 例如;插上了usb燈 就發光 插上手機就傳輸數據 因此反應表現不同 這就叫作 利用重寫基類方法實現多態。
里氏轉換原則:第一條 子類能夠直接賦值給父類至關於將子類強制轉化爲父類對象
父類提供一個方法若是是虛的,那麼子類能夠將該方法重寫只有子類前面加上一個override就叫作重寫基類方法, 重寫基類方法之後父類方法將不存在了,沒有了,只剩下子類方法
口訣: new 則隱藏 override 重寫 隱藏看類型 重寫只管新
1. 一個對象處於不一樣的環境 表現出不一樣的特徵 舉例 :七匹狼廣告
2.只管最新的那個重寫方法 同一個父類它裏面存在的是不一樣子類所表現出來不一樣子類的特徵就是一個usb插口 插上的東西不一樣反應各不相同 追尋同一種協議
:這就是倆種實現多態的方式
咱們的隱藏基類方法只管子類裏面new就好了基類我不用去管 可是重寫基類方法必須保證父類必定要virtual 若是父類不virtual不能重寫 而後子類能override。
里氏轉換原則:
1. 子類能夠直接賦值給父類(子類能夠直接轉化爲父類對象)
2.若是知足第一個條件的父類對象能夠強制轉化爲原來的子類對象
代碼舉例:
protocal 爲父類 iphone6爲子類 第一條代碼舉例: Protocal = iphone6( Pro); 第二條代碼舉例: protocal = new iphone(); iphone6 i= ( iphone ).protocal; 里氏轉換原則僞代碼: 1. 父類 父類對象 = new 子類(); 第一條 2. 子類 子類對象 = ()父類對象; 第二條 存在前提 第一條成立 重寫基類方法完整代碼示例: Class Protocal { public virtual void USB() { Console.WriteLine(「我是大牛,我寫的協議你要用嗎?繼承我吧」); } } Class Iphone6: Protual { public overide void USB() { Console.WriteLine(" 充電"); } } Class Light:Protual { public override void USB() { Console.WriteLine(「發光」); } } Class UDISC:Program { public override void USB() { Console.WriteLine("傳輸數據"): } } Class Program { static void Main(string [ ] args ) { new Light().USB(); new Iphone6().USB(); new UDISC().USB(); Console.ReadKey(); } } //由於插口只有一個因此: Protocal.protocal; protocal=new light; 着倆句代碼等同 Protocal protocal=new light ();
屬性
1.屬性相關
面向對象:就是找個對象幫你作事兒。
描述對象 :行爲 就是方法 特徵 就是字段 經過字段描述 屬性 :限制外界隨便訪問字段的一種方式
定義字段時好比 string mark ; 此時 默認訪問級別爲private
屬性的演變過程代碼以下:
Class 方便麪 { private string mark; public void set_mark(string value )//只寫 就是修改值 { mark=value; } public string get_Mark()//只讀 就是讀取 { return mark; } } Class Program { static void Main (string [] args) { 方便麪 f = new 方便麪 (); f.set_Mark('康師傅紅燒牛肉麪'); Console.WriteLine( f.get.Mark () ); } } //這倆個方法雖然能完成要求 可是麻煩 因此就簡化了 public string Mark() { get{ return mark ;} set{ mark = value ;} } 用反編譯(神器)IL代碼 看出屬性的本質就是方法 屬性不能存儲數據 字段才能存儲 自動屬性 : public string Zidongshuxing { get; set; }
構造方法也有重載 有重載就考慮到調用 怎麼調用 this 就出現了 當前類中(this)
this: 當調用 指定構造方法後有this的時候
public Constructure (): this () { } 這時先執行this(「1」)而後纔是 public Construeture()
有繼承關係默認調用父類構造函數 (無參數的那個)
若是此時父類構造方法有參數就回出錯 這時手動添加無參構造方法或者傳入參數也能夠指定調用
爲社麼要隱藏基類或者重寫基類由於當你繼承時有new了對象 當調用方法時 默認會調用父類而此時你的父類方法不是你須要的,你須要 子類方法,這時你得跳過父類方法那麼只能把父類方法隱藏或者讓它消失。
IS 運算符用法
is關鍵字表示 判斷 person [ i ] is chinese 左邊對象 和右邊對象是否是相等 就是判斷Person 【i】可否強轉位 chinese 這種類型 若是強轉成功返回True 失敗則返回 false 代碼示例以下:
Class TTT { } Class Program { static void Main (string [ ] args ) { TTT t = new TTT(); //成功 bool b = t is object ; //此時是true 因此強轉 bool b=t is string ; //此時是false 強轉失敗 } } 代碼示例2: Class TTT { } Class BBB:TTT { } Class Program { static void Main (string [ ] args ) { TTT t = new TTT(); bool b = t is BBB; //若是這裏強轉失敗 則是false; 失敗緣由不符合里氏轉換原則 TTT t = new BBB(); bool b = t is BBB();//若是這時是true 強轉成功 } } //這就是IS的用法 就是看左邊能不能轉成右邊 看返回true仍是false
AS運算符:
My temp = myBase(對象) as MySub(類型); 若是此時MyBase能轉換位MySub轉換好了 就把值賦給temp 若是不能轉換我就給temp=null; 可是is判斷 myBase is MySub; 代表它能不能判斷返回的是true仍是false。
多態 爲了程序可擴展性:
開放封閉原則 對擴展開放 對修改封閉(訪問修飾符的體會)
多態 重寫經典範例 : Tostring
多態與Tostring()方法 Tostring 對類型有很重要的意義 任何類型都具有Tostring 方法緣由是object是根類提供了Tostring()方法 可是要注意Tostring是虛方法
代碼以下:
//默認將你輸入類型的名字打印出來只輸出類型名 Class MyClasss { public string Name1; public string Name2; public string Name3; public override string Tostring () { return Name1+Name2+Name3; } Struct MyStruct { public string Name ; public override string Tostring () { return 「哈哈哈」; } } } Class Program { static void Main ( string [ ] args ) { string [ ] str ={ "1", "2", "3", "4",}; Myclass myclass= new MyClass(); myClass.Name="我是myclass"; Mystruct myStruct; mystruct name="我是mystruct"; Console.WriteLine( str ); → str.Tostring(); Console.WriteLine( myclass ); → myclass.Tostring(); Console.WriteLine( mystruct ); } } //這些代碼就是默認調用Tostring方法。 此時只能輸出類型。不過你寫了Tostring()方法在構造類型中就能夠自定義打印 // public override string Tostring () // return
多態的使用 :將不一樣對象都看成父類來看屏蔽掉各個對象間的不一樣 寫出通用代碼作出通同編程 以適應需求變化
通俗講: 我設計一個USB協議或者我作一個usb接口 你全部的廠商生產usb產品時 無論u盤也好 mp3也好仍是其餘的你只要符合我這個接口標準我就能夠拿來用你是什麼東西我就會實現什麼東西
多態: 前提條件 :是方法簽名必須相同 多態的保障: 1 繼承 2 里氏轉換原則
is 和 as 判斷父類繼承 判斷接口實現 判斷拆箱與裝箱 多態的實現2 抽象類 Abstract
抽象類 抽象方法
class Protocal (協議)
{
public void USB ()
{
}
}
此時 對於協議而言不是一個具體的東西好比類是車模當實例化類時就是把車模作成一個汽車 就是對象了 可是方法是對象得行爲此時這個協議沒法實例化爲對象時(沒有具體的對象 談何對象得行爲) 方法體就寫不出來 只有倆個大括號
因此
public void USB () { }
此時大括號空着 當以當重寫時這裏就得加一個virtual 變成
public virtual void USB() { }
當這個方法沒法寫出方法體時 大括號就沒有意義因此就不寫了 變成 public virtual void USB ()
但此時不符合方法的語法就會出錯 語法錯誤 因爲此時父類沒法實例化爲對象沒有對象得行爲就是方法 因此此時方法寫不出來或者此時也不須要實例化或者是不知道怎麼樣實現 好比動物兔子得叫聲 你不能寫成兔子吧 因此就出現瞭解決這個問題得方法Abstract
此時代碼變爲 public abstract void USB()//表示一個抽象得方法就不用寫方法體了;此時就不會出現由於方法語法問題而出錯
一個類型只有一個方法 當這個類型實例化爲對象得時候就會調用類的構造函數對對象賦值可是這時沒法實例化怎麼調用這個抽象方法呢因此此時只得在類前面加abstruct 表示 抽象類 代碼示例:
abstruct class Protocal { }
沒有方法體得方法→抽象方法→用abstruct修飾 包含抽象方法得類必須是抽象類 不能實例化得類→抽象類 抽象類中能夠包含非抽象成員 代碼以下:
abstruct class Protocal { public abstruct void Protocal public void Func() --------->正常方法不是抽象得 它是爲子類服務得 就是說子類能夠調用它 { Console.WriteLine(「Function」); } } //那麼如何調用抽象方法呢! Protocal p= new Iphone (); P.USB(); P.USB(); 用法上徹底和重寫virtocal同樣 就是語法上要求多一點 若是變成 public abstruct void USB () { //空實現 } //這樣也不對 雖然你沒有寫方法體(實現體)可是有大括號在表示 空實現
抽象類裏能夠包含非抽象成員就天然包括字段天然也就有初始化過程 這不就須要構造函數了 由於構造函數得做用就是初始化 因此有構造方法 只不過不能被外界調用因此通常把抽象類得構造方法通常設爲private 或者 protect 使其受到保護
抽象類依舊是描述對象得模版 :
1. 抽象類能夠有非抽象成員
2.抽象類不能實例化
3.抽象類存在就是爲了被繼承 所以不能設爲private
4.抽象方法就是爲了讓子類重寫
注意:抽象類不能實例化 比通常類 多 抽象成員 代碼以下 :
案例:動物 animal 都有 Bark (叫聲)方法,可是貓和狗叫聲不一樣 。 shift + ait +f10 自動添加虛方法代碼 abstruct class Animal { public abstruct void Bark (); } class Dog; Animal { public override void Bark(); { Console.WriteLine("汪汪汪"); } } class Cat ; Animal { public abstruct void Bark() { Console.WriteLine("喵喵喵"); } } class Program { static void Main (string [ ] args ) { Animal al = new dog (); al.Bark(); Animal a2; ----------------》這種寫法是由於父類只能new一個對象因此得換了方式只能這樣寫 Cat c = new Cat (); a2=c ; a2.Bark(); Console.ReadKey(); } }
自動屬性就是爲了方便程序員 簡化 操做
正常屬性執行過程:
class MyClass { private string test ; public string Test; { get { return text ;} 7 set { test = value ;} 3 4 } } Class Program { static void Main (string [ ] args ) { 1 MyClass class1=new MyClass(); 2 Class1.Test =「123」; 3 5 Console.WriteLine(class.Test); 6 8 } } // 2建立對象 3 賦值得時候其實是調用得set()方法,至關於把2123傳給→value 而後value再把值傳給text 當進行到6得時候就是打印屬性 此時訪問get方法就到7 這整個過程就叫作屬性的讀取與賦值 自動屬性 得執行過程和上面同樣自動屬性得數據存在哪裏了存在後臺(BackingField裏面)反編譯能夠看到
用什麼屬性視狀況而定
抽象屬性
abstruct Class MyBase { public override string Test { get; //只讀得抽象屬性 set; } } Class MySub : MyBase { string Test; public override string Test { get text ; } } //整個過程得含義就是 抽象類定義一個只讀得屬性而後再子類裏面提供字段並實現得這個過程就是以上代碼(抽象的屬性用法)
抽象屬性:難點1 比較繞
//抽象屬性代碼 abstruct class MyBase { public abstruct string Test { get ; set; } } //下面邊自動屬性了 Class MySub :myBase { public override string Test { get; set; } } //這裏的自動屬性等價於你單獨從新生成一個變量得屬性 注意此時不要受override影響
抽象屬性難點2 :
abstruct class MyTest { public abstract string Test { get;//次世代嗎就會報錯 由於沒法重寫得緣由是父類沒有提供set訪問而你下面的子類有set因此會出錯 } } Class MyTestSub: MyTest { string str; public override string Test { get { return str;} set( str =value ;) } }
抽象成員: 1 方法 2 屬性(屬性其實也是方法) 3 索引器 (本質是帶參數得屬性)凡事方法就能夠抽象 凡是方法相關得均可以抽象 除此以外所有砍掉 4 時間得聲明 (能夠看作屬性)
自動屬性裏面的set 和get 必須成對出現 缺一不可 由於它是對字段自動生成你知道那個字段的因此只能有get讀 set 寫缺一不可 自動屬性得特色
抽象屬性 使用的時候 通常是抽象類提供屬性 及可訪問性 這裏的抽象類指抽象父類 子類提供字段與屬性的實現 抽象屬性中get set 不用成對出現
接口語法
interface (接口關鍵字)+ IDoirable(接口名字) { } interface IDrivable { } //接口就是一個類型 大部分狀況下 默認第一個字母爲I 接口也是爲實現多態
類是對具體事物的抽象 諾記手機5180
抽象類是對一類具體事物的抽象 手機
接口是對一個能力的 抽象 打電話
接口定義能力即方法由子類進行實現 接口的存在就是爲了實現多態 接口能夠實現多繼承 就是能夠繼承多個接口
類的定義通常格式:
[public ] [static ] class 類名:[基類名] [ [ 接口名] ,接口名] { //成員 }
因爲接口能夠實現多繼承因此就解決了繼承體積龐大的問題
接口語法注意:
命名通常使用I開頭
成員沒有訪問修飾符
無實現體
派生類必須實現接口方法 除了抽象類
接口成員必須抽象
爲何要有顯式實現接口 爲了不方法重名
實現方式 接口名.方法名()
顯式實現的方法只有接口對象才能調用
面向對象編程儘可能儘量使用抽象數據不是用具體數據 由於能夠實現多態比較靈活
通常定義執行過程 接口 抽象類 父類 子類 的順序 通常先定義接口 再定義抽象類
注意: 避免定義 體積龐大 功能齊全的接口 由於使用簡單的結構框架方便靈活調用 單一原則 一個接口只描述一個功能 接口組合使用
抽象類和接口的區別:
抽象類適用於一系列而且有須要繼承的成員 →USB協議
接口適用於不一樣系列的類相同的動做 → 功能
對於不是相同的系列但具備相同的行爲這個據考慮接口
值類型 值得傳遞 數據存儲再堆棧 → 複製文件 →valuetype→ object
引用類型 先建立對象再傳值→ 建立快捷方式 無論你建立多少個快捷方式對象指向只有一個 →object
參數的傳遞 ref 和out :ref和out均可以實現參數傳遞的時候在方法內修改的參數結果再外界受到影響
注意:使用ref和out均可以將參數傳入方法並保留再方法中對參數賦值時的影響
即參數再方法中被修改了方法結束後結果仍然保留方法中最後一次被修改的值這就是引用傳遞
ref reference 引用 引用表示方法中的是變量得引用就是快捷方式 使用前要賦值 把數據傳進去
out 參數用來輸出 即方法中對變量得修改就是爲了讓其輸出到外邊得 使用後要賦值 把數據傳出去
params:
一個方法只能有一個params參數(傳進去)而且只能是最後一個位置
static void Main ( string [ ] args) { int [].nums={1, 2, 3}; Func (111,nums,10,20,30); } static void Func (int i ; int [ ] nums ,params int [ ] ) { } //傳參數得是偶 int i 對應 111 int[ ] nums 對應 nums 剩下得10 20 30 所有被params打包傳遞 因此params參數就是最後一個位置而且每一個方法僅有一個params
靜態成員與實例成員 表示 static 表示它修飾得這個成員叫作靜態成員
就是那些爲了讓你使用方便並且頻繁出現得東西爲了下次還能使用static修飾它就不會被垃圾回收下次你要是用了直接調用他們 空間都分配在靜態儲存區
靜態成員做用於整個應用 程序不受clr(運行庫)得控制 不會垃圾釋放掉
如何定義靜態成員 static 如何調用 與實例成員調用關係
定義 :
public static int num;
調用 : (類名.成員名)
靜態類方法中不能直接調用非靜態成員 也就是實例成員
靜態成員屬於整個類型 實例成員屬於某個對象
對靜態成員得訪問會將結果保留下來 誰都能訪問
靜態類 當你這個類裏面全是靜態成員得時候 靜態類只能包含靜態成員
性質修飾:static 與abstruct 級別相同 只能用一個 與public 與 internal 沒有關係 因此這是倆碼事。
靜態成員屬於全部類 非靜態成員屬於當前實例 靜態類的生命週期從第一次使用開始到程序結束 所以儘可能少用(佔內存)
try { //可能出現異常得代碼 一旦出現異常得代碼 就跳到catch try中其後得代碼就不執行了 } catch { //一旦出現異常就執行這裏代碼 記錄出錯 } finaly { //釋放資源 不管是否出現異常都執行finaly裏面代碼 }