1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        面試 | .NET基礎(chǔ)知識快速通關(guān)!

        共 5365字,需瀏覽 11分鐘

         ·

        2021-05-11 16:33


        【.NET總結(jié)/Edison Zhou

        此系列文章為我在2015年發(fā)布于博客園的.NET基礎(chǔ)拾遺系列,它十分適合初中級.NET開發(fā)工程師在面試前進(jìn)行一個系統(tǒng)的復(fù)習(xí),因此我將其搬到公眾號分享與你。

        本文為第六篇,我們會對.NET的集合與泛型相關(guān)考點(diǎn)進(jìn)行基礎(chǔ)復(fù)習(xí),全文會以Q/A的形式展現(xiàn),即以面試題的形式來描述。

        1int[]是值類型還是應(yīng)用類型?

        在.NET中的數(shù)組類型和C++中區(qū)別很大,.NET中無論是存儲值類型對象的數(shù)組還是存儲引用類型的數(shù)組,其本身都是引用類型,其內(nèi)存也都是分配在堆上的。它們的共同特征在于:所有的數(shù)組類型都繼承自System.Array,而System.Array又實(shí)現(xiàn)了多個接口,并且直接繼承自System.Object。不同之處則在于存儲值類型對象的數(shù)組所有的值都已經(jīng)包含在數(shù)組內(nèi),而存儲引用類型對象的數(shù)組,其值則是一個引用,指向位于托管堆中的實(shí)例對象。

        下圖直觀地展示了二者內(nèi)存分配的差別(假設(shè)object[]中存儲都是DateTime類型的對象實(shí)例):

        在.NET中CLR會檢測所有對數(shù)組的訪問,任何視圖訪問數(shù)組邊界以外的代碼都會產(chǎn)生一個IndexOutOfRangeException異常。

        2你知道數(shù)組之間如何轉(zhuǎn)換的嗎?

        數(shù)組類型的轉(zhuǎn)換需要遵循以下兩個原則:

        (1)包含值類型的數(shù)組不能被隱式轉(zhuǎn)換成其他任何類型;

        (2)兩個數(shù)組類型能夠相互轉(zhuǎn)換的一個前提是兩者維數(shù)相同;

        我們可以通過以下代碼來看看數(shù)組類型轉(zhuǎn)換的機(jī)制:

        // 編譯成功string[] sz = { "a", "a", "a" };object[] oz = sz;// 編譯失敗,值類型的數(shù)組不能被轉(zhuǎn)換int[] sz2 = { 1, 2, 3 };object[] oz2 = sz;// 編譯失敗,兩者維數(shù)不同string[,] sz3 = { { "a", "b" }, { "a", "c" } };object[] oz3 = sz3;

        除了類型上的轉(zhuǎn)換,我們平時還可能會遇到內(nèi)容轉(zhuǎn)換的需求。例如,在一系列的用戶界面操作之后,系統(tǒng)的后臺可能會得到一個DateTime的數(shù)組,而現(xiàn)在的任務(wù)則是將它們存儲到數(shù)據(jù)庫中,而數(shù)據(jù)庫訪問層提供的接口只接受String[]參數(shù),這時我們要做的就是把DateTime[]從內(nèi)容上轉(zhuǎn)換為String[]對象。當(dāng)然,慣常做法是遍歷整個源數(shù)組,逐一地轉(zhuǎn)換每個對象并且將其放入一個目標(biāo)數(shù)組類型容器中,最后再生成目標(biāo)數(shù)組。But,這里我們推薦使用Array.ConvertAll方法,它提供了一個簡便的轉(zhuǎn)換數(shù)組間內(nèi)容的接口,我們只需指定源數(shù)組的類型、對象數(shù)組的類型和具體的轉(zhuǎn)換算法,該方法就能高效地完成轉(zhuǎn)換工作。

        下面的代碼清楚地展示了普通的數(shù)組內(nèi)容轉(zhuǎn)換方式和使用Array.ConvertAll的數(shù)組內(nèi)容轉(zhuǎn)換方式的區(qū)別:

        public class Program{    public static void Main(string[] args)    {        String[] times ={"2008-1-1",                        "2008-1-2",                        "2008-1-3"};
        // 使用不同的方法轉(zhuǎn)換 DateTime[] result1 = OneByOne(times); DateTime[] result2 = ConvertAll(times);
        // 結(jié)果是相同的 Console.WriteLine("手動逐個轉(zhuǎn)換的方法:"); foreach (DateTime item in result1) { Console.WriteLine(item.ToString("yyyy-MM-dd")); } Console.WriteLine("使用Array.Convert方法:"); foreach (DateTime item2 in result2) { Console.WriteLine(item2.ToString("yyyy-MM-dd")); }
        Console.ReadKey(); }
        // 逐個手動轉(zhuǎn)換 private static DateTime[] OneByOne(String[] times) { List<DateTime> result = new List<DateTime>(); foreach (String item in times) { result.Add(DateTime.Parse(item)); } return result.ToArray(); }
        // 使用Array.ConertAll方法 private static DateTime[] ConvertAll(String[] times) { return Array.ConvertAll(times, new Converter<String, DateTime> (DateTimeToString)); }
        private static DateTime DateTimeToString(String time) { return DateTime.Parse(time); }}

        從上述代碼可以看出,二者實(shí)現(xiàn)了相同的功能,但是Array.ConvertAll不需要我們手動地遍歷數(shù)組,也不需要生成一個臨時的容器對象,更突出的優(yōu)勢是它可以接受一個動態(tài)的算法作為具體的轉(zhuǎn)換邏輯。當(dāng)然,明眼人一看就知道,它是以一個委托的形式作為參數(shù)傳入,這樣的機(jī)制保證了Array.ConvertAll具有較高的靈活性。

        3能說說泛型的基本原理嗎?

        泛型的語法和概念類似于C++中的template(模板),它是.NET 2.0中推出的眾多特性中最為重要的一個,方便我們設(shè)計(jì)更加通用的類型,也避免了容器操作中的裝箱和拆箱操作。

        假如我們要實(shí)現(xiàn)一個排序算法,要求能夠針對各種類型進(jìn)行排序。按照以前的做法,我們需要對int、double、float等類型都實(shí)現(xiàn)一次,但是我們發(fā)現(xiàn)除了數(shù)據(jù)類型,其他的處理邏輯完全一致。這時,我們便可以考慮使用泛型來進(jìn)行實(shí)現(xiàn):

        public static class SortHelper<T> where T : IComparable{    public static void BubbleSort(T[] array){        int length = array.Length;        for (int i = 0; i <= length - 2; i++)        {            for (int j = length - 1; j >= 1; j--)            {                // 對兩個元素進(jìn)行交換                            if (array[j].CompareTo(array[j - 1]) < 0)                {                    T temp = array[j];                    array[j] = array[j - 1];                    array[j - 1] = temp;                }            }        }    }}

        Tips:Microsoft在產(chǎn)品文檔中建議所有的泛型參數(shù)名稱都以T開頭,作為一個中編碼的通用規(guī)范,建議大家都能遵守這樣的規(guī)范,類似的規(guī)范還有所有的接口都以I開頭。

        泛型類型和普通類型有一定的區(qū)別,通常泛型類型被稱為開放式類型,.NET中規(guī)定開放式類型不能實(shí)例化,這樣也就確保了開放式類型的泛型參數(shù)在被指定前,不會被實(shí)例化成任何對象(事實(shí)上,.NET也沒有辦法確定到底要分配多少內(nèi)存給開放式類型)。為開放式的類型提供泛型的實(shí)例導(dǎo)致了一個新的封閉類型的生成,但這并不代表新的封閉類型和開放類型有任何繼承關(guān)系,它們在類結(jié)構(gòu)圖上是處于同一層次,并且兩者之間沒有任何關(guān)系。下圖展示了這一概念:

        此外,在.NET中的System.Collections.Generic命名空間下提供了諸如List<T>、Dictionary<T>、LinkedList<T>等泛型數(shù)據(jù)結(jié)構(gòu),并且在System.Array中定義了一些靜態(tài)的泛型方法,我們應(yīng)該在編碼實(shí)踐時充分使用這些泛型容器,以提高我們的開發(fā)和系統(tǒng)的運(yùn)行效率。

        4泛型的主要約束和次要約束是什么?

        當(dāng)一個泛型參數(shù)沒有任何約束時,它可以進(jìn)行的操作和運(yùn)算是非常有限的,因?yàn)椴荒軐?shí)參進(jìn)行任何類型上的保證,這時候就需要用到泛型約束。泛型的約束分為:主要約束和次要約束,它們都使實(shí)參必須滿足一定的規(guī)范,C#編譯器在編譯的過程中可以根據(jù)約束來檢查所有泛型類型的實(shí)參并確保其滿足約束條件。

        (1)主要約束

        一個泛型參數(shù)至多擁有一個主要約束,主要約束可以是一個引用類型、class或者struct。如果指定一個引用類型(class),那么實(shí)參必須是該類型或者該類型的派生類型。相反,struct則規(guī)定了實(shí)參必須是一個值類型。下面的代碼展示了泛型參數(shù)主要約束:

        public class ClassT1<T> where T : Exception{    private T myException;    public ClassT1(T t){        myException = t;    }    public override string ToString(){        // 主要約束保證了myException擁有source成員        return myException.Source;    }}
        public class ClassT2<T> where T : class{ private T myT; public void Clear(){ // T是引用類型,可以置null myT = null; }}
        public class ClassT3<T> where T : struct{ private T myT; public override string ToString(){ // T是值類型,不會發(fā)生NullReferenceException異常 return myT.ToString(); }}

        泛型參數(shù)有了主要約束后,也就能夠在類型中對其進(jìn)行一定的操作了。

        (2)次要約束

        次要約束主要是指實(shí)參實(shí)現(xiàn)的接口的限定。對于一個泛型,可以有0到無限的次要約束,次要約束規(guī)定了實(shí)參必須實(shí)現(xiàn)所有的次要約束中規(guī)定的接口。次要約束與主要約束的語法基本一致,區(qū)別僅在于提供的不是一個引用類型而是一個或多個接口。例如我們?yōu)樯厦娲a中的ClassT3增加一個次要約束:

        public class ClassT3<T> where T : struct, IComparable{    ......      }
        End總結(jié)

        本文總結(jié)復(fù)習(xí)了.NET的集合與泛型處理相關(guān)的重要知識點(diǎn),下一篇會總結(jié).NET中流與序列化處理相關(guān)的重要知識點(diǎn),歡迎繼續(xù)關(guān)注!







        回復(fù) 【關(guān)閉】學(xué)關(guān)
        回復(fù) 【實(shí)戰(zhàn)】獲取20套實(shí)戰(zhàn)源碼
        回復(fù) 【被刪】學(xué)
        回復(fù) 【訪客】學(xué)
        回復(fù) 【小程序】學(xué)獲取15套【入門+實(shí)戰(zhàn)+賺錢】小程序源碼
        回復(fù) 【python】學(xué)微獲取全套0基礎(chǔ)Python知識手冊
        回復(fù) 【2019】獲取2019 .NET 開發(fā)者峰會資料PPT
        回復(fù) 【加群】加入dotnet微信交流群

        谷歌靈魂插件,98%的程序員都好評!


        再見Vip,免費(fèi)看網(wǎng)飛影視大片!


        瀏覽 58
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产成人精品免费久久久 | 蜜乳一区二区三区免费 | 男人j捅女人 | www.天天操.com | 美女黄网站免费 | 午夜熟睡乱子伦视频 | 好深好湿好硬顶到了好爽小喜 | 玖玖资源站在线观看 | 俺去也天天幹 | 国精产品乱码一区一区三区四区 |