面向對象的三大特征: 封裝性 繼承性 多態性
一.繼承:類與類的關系
為什么會用繼承:減少代碼重復 優化 空間內存 實現多態
class 基類{ //基類成員}class 子類:基類{ //子類成員}
判斷繼承關系 用進行進行判斷--》子類對象 is 父類成員
例如 諾基亞手機 諾基亞280 諾基亞板磚007
繼承特征 :1.單根性 一個只能繼承自一個類 不可能繼承倆個類
2.傳遞性 爺爺 父親 孫子
3.派生于object根類(c#范圍) c#里面的所有成員都來源于object 用于實現多態
注意: 1.繼承中構造函數的問題 其實就是執行順序
2.可以手動添加一個無參構造方法
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里面代碼}
新聞熱點
疑難解答