15_中級(jí)C#

類的定義

  1. 面向?qū)ο缶幊?,結(jié)構(gòu)化編程
  2. 類,定義了每一個(gè)對(duì)象
  3. 類,就是創(chuàng)造對(duì)象的模板,數(shù)據(jù)+功能
  4. 類的成員,數(shù)據(jù)成員+函數(shù)成員
    4.1 數(shù)據(jù)成員:是包含類的數(shù)據(jù)(字段+常量和事件的成員)
    4.2 函數(shù)成員:提供了操作類中數(shù)據(jù)的某些功能(方法+屬性+構(gòu)造方法+終結(jié)器(析構(gòu)方法)+運(yùn)算符+索引器)
  5. 類的字段和方法
    5.1 字段,就是數(shù)據(jù)成員(訪問修飾符,類型,字段名稱)
    5.2 方法,就是函數(shù)成員(訪問修飾符,返回值類型,方法名稱)
  6. 求平方是double類型,一般會(huì)把他轉(zhuǎn)換為float類型,強(qiáng)行轉(zhuǎn)換
  7. 類中,編程規(guī)范上,一般把字段設(shè)置成privte,那就只能在單一的類中使用,所以需要用個(gè)Set+this.去重新設(shè)置,以保安全

構(gòu)造過程

  1. 我們構(gòu)造對(duì)象的時(shí)候,對(duì)象的初始化過程是自動(dòng)完成的,但是在初始化對(duì)象的過程中有的時(shí)候需要做一些額外的工作,例如需要初始化對(duì)象存儲(chǔ)的數(shù)據(jù),構(gòu)造函數(shù)就是用于初始化數(shù)據(jù)的函數(shù)。
    ...
    public class MyClass{
    public MyClass(){
    這個(gè)構(gòu)造函數(shù)的函數(shù)體
    }
    }
    ...
    當(dāng)我們使用new關(guān)鍵字創(chuàng)建類的時(shí)候,就會(huì)調(diào)用構(gòu)造方法。我們一般會(huì)是用構(gòu)造方法進(jìn)行初始化數(shù)據(jù)的一些操作。構(gòu)造函數(shù)可以進(jìn)行重載,跟普通函數(shù)重載是一樣的。
    注意:
    當(dāng)我們不寫,任何構(gòu)造函數(shù)的時(shí)候,編譯器會(huì)提供給我們一個(gè)默認(rèn)的無參的構(gòu)造函數(shù),但是如果我們定義了一個(gè)或者多個(gè)構(gòu)造函數(shù),編譯器就不會(huì)再提供默認(rèn)的構(gòu)造函數(shù)。

屬性的定義

  1. 演示
    ...
    public int MyIntProperty
    {
    get
    {
    Console.WriteLine("屬性中的get塊被調(diào)用");
    return 100;
    }
    set
    {
    Console.WriteLine("屬性中的set塊被調(diào)用");
    Console.WriteLine("在set塊中訪問value的值是:" + value);
    }
    }
    ...
    set值:當(dāng)給屬性設(shè)置值的時(shí)候,會(huì)調(diào)用set方法
    get值:當(dāng)給屬性取值的時(shí)候,會(huì)調(diào)用get方法
    兩者不要求同時(shí)存在,如果沒有g(shù)et塊,那就不能通過屬性取值了。
  2. get+set的作用:
    1)通過set方法,在設(shè)置值之前,做一些校驗(yàn)的工作。
    2)可以設(shè)置只讀和只寫,在set或get那,用private / public
  1. Public string Name{get;set;}

匿名類型

  1. 用引用來添加其他庫的類別
  2. 只是要public一次
  3. 當(dāng)var,匿名類型被賦值了以后,那他的形式就被確定下來了,不能再變

堆和棧 程序運(yùn)行時(shí)的內(nèi)存區(qū)域

  1. 我們把內(nèi)存分為堆空間和棧空間
    1)棧空間比較小,但讀取速度快
    2)堆空間比較大,但讀取速度慢

  2. 棧的特征(先入后出)
    1)數(shù)據(jù)只能從棧的頂端插入,和刪除
    2)把數(shù)據(jù)放入棧頂,稱為入棧(push)
    3)把棧頂刪除數(shù)據(jù)稱為出棧(pop)

  3. 堆的特征
    1)堆是一塊內(nèi)存區(qū)域,與棧不同,堆里的內(nèi)存能夠以任意順序存入和移除

  4. .NET當(dāng)中的GC Garbage Collection 垃圾回收器
    CLR的CG就是內(nèi)存管理機(jī)制,我們寫程序不需要關(guān)心內(nèi)存的使用,因?yàn)檫@些都是CLR幫我們做了
    過程:
    1)程序在堆里保存了三個(gè)對(duì)象
    2)后來的程序中,其中的一個(gè)對(duì)象不再被程序使用
    3)垃圾收集器發(fā)現(xiàn)無主對(duì)象并釋放他
    4)垃圾收集之后,被釋放對(duì)象的內(nèi)存可以被重用

值類型和引用類型,在內(nèi)存中的存儲(chǔ)

  1. 類型被分為兩種,值類型(整數(shù)+bool+struct+char+小數(shù))+引用類型(string,數(shù)組,自定義的類,內(nèi)置的類)

  2. 值類型,只需要一段內(nèi)存,用于存儲(chǔ)實(shí)際的數(shù)據(jù)(單獨(dú)定義的時(shí)候,放在棧中)

  3. 引用類型,需要兩段內(nèi)存,第一段存儲(chǔ)實(shí)際數(shù)據(jù),他總是在堆中。第二段是一個(gè)引用,指向數(shù)據(jù)在堆中的存放位置(指向第一段內(nèi)存)

  4. 當(dāng)我們使用了引用類型賦值的時(shí)候,其實(shí)是賦值的是引用類型。賦值的話,其實(shí)是調(diào)換內(nèi)存地址的指向

  5. //如果數(shù)組是一個(gè)值類型的數(shù)組,那么數(shù)組中直接存儲(chǔ)數(shù)值。
    //如果是一個(gè)引用類型的數(shù)組,那么數(shù)組中存儲(chǔ)的是引用地址。
    ...
    static void Test1()
    {
    int i = 34;
    int j = 34;
    int temp = 34;
    char c = 'a';
    bool b = true;
    }
    ...


    Test1

    ...
    static void Test2()
    {
    int i = 34;
    int j = 234;
    string name = "siki";
    }
    ...


    Test2

    ...
    static void Test3()
    {
    string name = "siki";
    string name2 = "taikr";
    name = name2;
    name = "google";
    Console.WriteLine(name + ":" + name2);
    }
    ...
    Test3

    ...
    static void Test4()

    {
    Vector3 v = new Vector3();
    v.x = 100;
    v.y = 100;
    v.z = 100;
    Vector3 v2 = new Vector3();
    v2.x = 200;
    v2.y = 200;
    v2.z = 200;
    v2 = v;
    v2.x = 300;
    Console.WriteLine(v.x);
    }

class Vector3
{
public float x, y, z;
}
...

Test4

...
static void Test5()
{
Vector3[] vArray = new Vector3[] { new Vector3(), new Vector3(), new Vector3() };
//如果數(shù)組是一個(gè)值類型的數(shù)組,那么數(shù)組中直接存儲(chǔ)數(shù)值。
//如果是一個(gè)引用類型的數(shù)組,那么數(shù)組中存儲(chǔ)的是引用地址。
Vector3 v1 = vArray[0];
vArray[0].x = 100;
v1.x = 200;
Console.WriteLine(vArray[0].x);
}
...


Test5

繼承

實(shí)現(xiàn)繼承:
表示一個(gè)類型派生于一個(gè)基類型,他擁有該基類型的所有成員字段和函數(shù)。在實(shí)現(xiàn)繼承中,派生類型采用基類型的每個(gè)函數(shù)的實(shí)現(xiàn)代碼,除非在派生類型的定義中指定重寫某個(gè)函數(shù)的實(shí)現(xiàn)代碼。在需要給現(xiàn)有的類型添加功能或許多相關(guān)類型共享一組重要公共功能時(shí),這種類型的繼承非常有用。

接口繼承:
表示一個(gè)類型只繼承了函數(shù)的簽名,沒有繼承任何實(shí)現(xiàn)代碼,在需要指定該類型具有某些可用的特性時(shí),最好使用這種類型的繼承。

多重繼承:
使用多重繼承的有點(diǎn)是有爭議的:一方面,毫無疑問,可以使用多重繼承編寫非常復(fù)雜、但很緊湊的代碼。另一方面,使用多重實(shí)現(xiàn)繼承的代碼常常很難理解和調(diào)試。但是,C#的主要設(shè)計(jì)目標(biāo)是簡化健壯代碼,所以C#不支持多重實(shí)現(xiàn)繼承。
但是,C#允許類型派生自多個(gè)接口,多重接口繼承。這說明,C#類可以派生自另一個(gè)類和任意多個(gè)接口。更準(zhǔn)確地說,system.object是一個(gè)公共的基類,所以每個(gè)C#都有一個(gè)基類,還有可以有任意多個(gè)基接口。

...
class Program
{
static void Main(string[] args)
{
//Boss boss = new Boss();
//boss.AI();//繼承父類里面所有的數(shù)據(jù)成員和函數(shù)成員,都會(huì)繼承到子類里面
//boss.Attack();

        //Enemy enemy;
        //enemy = new Boss();//父類聲明的對(duì)象,可以用子類去構(gòu)造.不可以反過來
        ////enemy雖然使用父類進(jìn)行了聲明,但是使用了子類構(gòu)造,所以本質(zhì)上是一個(gè)子類類型,我們可以強(qiáng)制類型轉(zhuǎn)換,轉(zhuǎn)換成子類類型
        //Boss boss = (Boss)enemy;
        //boss.Attack();

        Enemy enemy = new Enemy();
        Boss boss = (Boss)enemy;//這樣會(huì)錯(cuò)誤,因?yàn)橐粋€(gè)對(duì)象是什么類型的,主要看他是什么構(gòu)造來定。這里的enemy使用了父類的構(gòu)造函數(shù),所以只有弗雷中的字段和方法,不能被強(qiáng)制轉(zhuǎn)換成子類
        //可以使用父類去聲明對(duì)象,用子類去實(shí)例化
        Console.ReadKey();
    }
}

class Enemy
{
private float hp;
private float speed;

    public float HP
    {
        get { return hp; }
        set { hp = value; }
    }

    public float Speed
    {
        get { return speed; }
        set { speed = value; }
    }

    public void AI()
    {
        Console.WriteLine("這里是Enemy1的公有AI方法");
    }

    public void Move()
    {
        Console.WriteLine("這里是Enemy1的公有move方法");
    }
}

class Boss: Enemy
{
public void Attack()
{
AI();
Move();
HP = 100;//父類里面公有的數(shù)據(jù)和方法,才能被訪問

        Console.WriteLine("Boss正在進(jìn)行攻擊");
    }
}

...

虛方法

  1. 把一個(gè)基類函數(shù)聲明為virtual,就可以在任何派生類中重寫該函數(shù)
  2. 在派生類中,重寫另外一個(gè)函數(shù)時(shí),要使用override關(guān)鍵字顯示聲明
  3. 我們在子類里面重寫虛函數(shù)之后,不管在哪里調(diào)用都是用重寫之后的方法(只有當(dāng)通過子類的去構(gòu)造的時(shí)候,才會(huì)去調(diào)用子類的內(nèi)容)
  4. 虛方法重不重寫都沒關(guān)系,如果重寫了,就用新的,如果不重寫,就繼續(xù)調(diào)用虛方法

隱藏方法

  1. 如果簽名相同的方法在基類和派生類中都進(jìn)行了聲明,但是該方法沒有分別聲明為virtual和overri,派生類就會(huì)隱藏基類方法(要使用new方法進(jìn)行聲明)
  2. 隱藏方法:如果使用子類聲明的對(duì)象,調(diào)用隱藏方法會(huì)調(diào)用子類的,如果使用父類聲明對(duì)象,那么就會(huì)調(diào)用父類中的隱藏方法
  3. 一般少用隱藏方法,會(huì)引起混亂

this base關(guān)鍵字

  1. this的作用就是,可以去調(diào)用當(dāng)前類的各種方法(基類+當(dāng)前自己的),不用其實(shí)也可以,但是有this,會(huì)好找很多。
  2. base只能訪問父類里面的方法

詳細(xì)定義內(nèi)容:

  1. this可以訪問當(dāng)前類中定義的字段、屬性和方法,有沒有this都可以訪問,有this可以讓編譯器給出提示,另外當(dāng)方法的參數(shù)跟字段重名的時(shí)候,使用this可以表明訪問的是類中的字段。this可以調(diào)用父類中的方法和字段,有沒有this都可以方法,但是加上base.IDE工具會(huì)給出提示,可以把所有的都顯示出來

抽象類

  1. C#允許把類和函數(shù)聲明為abstract,抽象類不能實(shí)例化,抽象類可以包含普通函數(shù)和抽象函數(shù),抽象函數(shù)就是只有函數(shù)定義沒有函數(shù)體。顯然,抽象函數(shù)本身也是虛擬的virtual(只有函數(shù)定義,沒有函數(shù)體實(shí)現(xiàn))
  2. 類是一個(gè)模板,那么抽象類就是一個(gè)不完整的模板,我們不能使用不完整的模板去構(gòu)造對(duì)象
  3. 可以用抽象類去聲明對(duì)象,但是不用他去構(gòu)造
  4. 當(dāng)我們繼承了一個(gè)抽象類的時(shí)候,必須去實(shí)現(xiàn)抽象方法

密封類和密封方法

  1. C#允許把類和方法聲明為sealed,對(duì)于類,這表示不能繼承該類;對(duì)于方法表示不能重寫該方法
  2. 什么時(shí)候會(huì)使用密封類和密封方法?
    答:防止重寫某些類導(dǎo)致代碼混亂,或,商業(yè)原因
    ...
    class DerivedClass:BaseClass//密封類無法被繼承
    {
    public sealed override void Move()//我們可以把重寫的方法聲明為密封方法,表示該方法不能被重寫
    {
    base.Move();
    }
    }

//sealed class BaseClass//這里聲明了一個(gè)密封類
class BaseClass
{
public virtual void Move()
{

    }
}

...

派生類的構(gòu)造函數(shù)

  1. 在子類中調(diào)用父類的默認(rèn)構(gòu)造函數(shù)(無參)(會(huì)先調(diào)用父類的,再調(diào)用子類的)
  2. 調(diào)用有參數(shù)的構(gòu)造函數(shù)
    ...
    class Program
    {
    static void Main(string[] args)
    {
    //DerivedClass o1 = new DerivedClass();
    DerivedClass o2 = new DerivedClass(1, 2);
    Console.ReadKey();
    }
    }

class BaseClass
{
private int x;
public BaseClass()
{
Console.WriteLine("base class 構(gòu)造函數(shù)");

    }

    public BaseClass(int x)
    {
        this.x = x;
        Console.WriteLine("y賦值完成");
    }
}

class DerivedClass:BaseClass
{
private int y;
public DerivedClass()
//調(diào)用父類中無參的構(gòu)造函數(shù),當(dāng)我們沒有在子類的構(gòu)造函數(shù)中顯示聲明調(diào)用父類的構(gòu)造函數(shù),默認(rèn)會(huì)調(diào)用父類中的無參構(gòu)造函數(shù)
{
Console.WriteLine("這個(gè)是DerivedClass無參的構(gòu)造函數(shù)");

    }
    public DerivedClass(int x, int y) : base(x)
    {
        this.y = y;
        Console.WriteLine("x賦值完成");
    }
}

...

關(guān)于訪問修飾符

  1. class的修飾符,只有在class前面聲明了public,才能去其他類中訪問
  2. new:成員用相同的簽名隱藏繼承的成員
  3. static:成員不作用于類的具體實(shí)例
  4. virtual:成員可以由派生類重寫
  5. abstract:虛擬成員定義了成員的簽名,但沒有提供實(shí)現(xiàn)代碼
  6. override:成員重寫了繼承的虛擬或抽象成員
  7. sealed:對(duì)于類,不能繼承自密封類,對(duì)于屬性和方法,成員重寫已繼承的虛擬成員,但任何派生類中的人和成員都不能重寫該成員,該修飾符必須與override一起使用
  8. extern:成員在外用另一種語言實(shí)現(xiàn)
  9. protected:(可以應(yīng)用于類型和內(nèi)嵌類型的所有成員)只能派生的類型能訪問該項(xiàng)。當(dāng)沒有繼承的時(shí)候,protected和private是一樣的。但是如果是在繼承函數(shù)里面,繼承還是是可以訪問到projected的。
  10. static可以修飾字段/方法,修飾字段的時(shí)候,表示這個(gè)字段是靜態(tài)的數(shù)據(jù),叫做靜態(tài)字段或靜態(tài)屬性,修飾方法的時(shí)候,叫做靜態(tài)函數(shù)。使用static修飾的成員,只能通過類名訪問。
  11. 當(dāng)我們構(gòu)造對(duì)象的時(shí)候,對(duì)象中只包含了普通字段,不包含靜態(tài)字段(只能通過類名去訪問,通過類名去賦值和取值)

定義和實(shí)現(xiàn)接口

  1. 定義一個(gè)接口在語法上,跟定義一個(gè)抽象類完全相同,但不允許提供接口中人和成員的實(shí)現(xiàn)方式,一般情況下,接口只能包含方法、屬性、索引器和事件的聲明
  2. 接口不能有構(gòu)造函數(shù),也不能有字段,接口也不允許運(yùn)算符重載
  3. 接口定義中不允許聲明成員的修飾符,接口成員都是公有的
  4. 接口也是可以相互繼承的,只是在繼承過程中,可能會(huì)有方法的層級(jí)嵌套,這個(gè)都需要去聲明

列表List的創(chuàng)建和使用

  1. 集合類:列表List
  2. 當(dāng)我們有很多類型一樣的數(shù)據(jù)時(shí)候,前面我們一般使用數(shù)組來進(jìn)行管理,但是這樣有一個(gè)缺點(diǎn)就是數(shù)組的大小是固定的。如果我們很多類型一樣的數(shù)據(jù),比如游戲得分,我們可以集合類來進(jìn)行管理,比如列表List,我們可以使用List很方便地添加數(shù)據(jù),刪除數(shù)據(jù)還有其他對(duì)數(shù)據(jù)的操作。
  3. 類型總結(jié):
    *創(chuàng)建列表:列表可以存儲(chǔ)任何類型的數(shù)據(jù),在創(chuàng)建列表對(duì)象的時(shí)候,首先要指定你要?jiǎng)?chuàng)建的這個(gè)列表要存儲(chǔ)什么類型(泛型)
List<int> scoreList = new List<int>();
            new List<int>() { 1, 2, 3 };
            new List<string>() { "one", "two" };
            var newScoreList = new List<int>();

*往列表里注入數(shù)據(jù)

scoreList.Add(12);
scoreLis.Add(45);

*如何取得列表中的數(shù)據(jù)?列表中的數(shù)據(jù)跟數(shù)組有點(diǎn)相似,索引從0開始,可以通過索引來訪問

scoreList[0];//訪問添加到列表中的第一個(gè)數(shù)據(jù)
  1. 關(guān)于列表的更多內(nèi)容
    1)列表初始容量為4,一旦發(fā)現(xiàn)超出范圍,就會(huì)擴(kuò)大為8,然后擴(kuò)大為16...依次增加
    2)直接設(shè)置個(gè)值,就可以減少數(shù)組的創(chuàng)建和刪除,可以提高性能
    3)可以通過Capacity屬性獲取和設(shè)置容量,intList.Capacity=100;
    4)注意容量和列表中元素個(gè)數(shù)的區(qū)別,容量是列表中用于存儲(chǔ)數(shù)據(jù)的數(shù)組長度通過capacity獲取,列表中的元素是我們添加進(jìn)去需要管理的數(shù)據(jù),通過count獲取

列表的遍歷

var scoreList = new List<int>();
            scoreList.Add(34);
            scoreList.Add(334);
            scoreList.Add(3344);
            scoreList.Add(344);
            scoreList.Add(32344);
            scoreList.Add(134);
            scoreList.Add(334);
            //for (int i = 0; i < scoreList.Count; i++)
            //{
            //    Console.Write(scoreList[i] + " ");
            //}

            foreach (var temp in scoreList)
            {
                Console.Write(temp + " ");
            }
            Console.ReadKey();

操作列表的屬性和方法

  1. 主要操作方法
    Capacity:獲取容量大小
    Add():添加元素
    Insert():插入元素
    [Index]:訪問元素
    Count:訪問元素個(gè)數(shù)
    RemoveAt():移除指定位置的元素
    IndexOf():取得一個(gè)元素所在列表的索引位置(從前往后搜)
    LastIndexOf():從后往前搜
    Sort():對(duì)列表中元素進(jìn)行從小到大排序
  2. 向指定索引位置插入元素,不可以超出元素個(gè)數(shù)

泛型類的定義

  1. 泛型:
    通過參數(shù)化類型來實(shí)現(xiàn)在同一份代碼上,操作多種數(shù)據(jù)類型。利用“參數(shù)化類型”將類型抽象化,從而實(shí)現(xiàn)靈活的復(fù)用
  2. 泛型類的定義
    定義一個(gè)泛型類指的是,定義一個(gè)類,這個(gè)類某些字段的類型是不確定的,這些類型可以在類構(gòu)造的時(shí)候確定下來。舉例:
    1)創(chuàng)建一個(gè)類處理int類型和double類型的相加:
class ClassA<T>//T代表一個(gè)數(shù)據(jù)類型,當(dāng)使用classA進(jìn)行構(gòu)造的時(shí)候,需要指定T的類型
    {
        private T a;
        private T b;

        public ClassA(T a, T b)
        {
            this.a = a;
            this.b = b;
        }

        public T GetSum()
        {
            return a +b;
        }

泛型方法

  1. 定義泛型方法就是定義一個(gè)方法,這個(gè)方法的參數(shù)可以是不確定的,可以當(dāng)調(diào)用這個(gè)方法的時(shí)候,再去確定方法參數(shù)的類型。
    可以實(shí)現(xiàn),任意類型組拼成字符串的方法
public static T GetSum<T>(T a, T b){
  return a+""+b;
}

GetSum<int>(23,12); GetSum<double>(23.2,12);

使用泛型和索引器,來實(shí)現(xiàn)一個(gè)我們自己的集合類MyList

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容