[AaronYang]C#人愛學不學[4]

來源:互聯網
上載者:User

標籤:

本文章不適合入門,只適合有一定基礎的人看。我更相信知識細節見高低,我是從4.0開始學的,終於有時間系統的學習C#5.0,是5.0中的知識,會特殊標記下。但寫的內容也可能含有其他版本framework的知識,也是為了方便自己更好的記憶C#知識。文章內容都是自己總結,無抄襲,如果你覺得文章檔次太低,請大牛繞道 --Aaronyang的部落格(www.ayjs.net)
1. 泛型-是C#的泛型

 1.1 效能方面比非泛型好點,比如拆箱裝箱的問題。個人感覺代碼可讀性更好吧。還有就是 寫代碼可能可以寫出很精彩的代碼。命名用T開頭,加有意義的單詞,比如 Converter<TInput,TOut>,XX<TKey,TValue>

 1.2 題目:不百度,請自己至少列舉5個 例如List<T>使用泛型的C#中的常用對象

 1.3 自己寫個鏈式,並使用泛型知識的demo

       1.定義鏈式節點, 前一個節點,後一個節點,再加上自己這個節點就OK了 

   //定義鏈式節點, 前一個節點,後一個節點,再加上自己這個節點就OK了    public class MyLinkedNode<T> {         public MyLinkedNode(T value){            this.Value = value;        }        public T Value{get;private set;}        /// <summary>        /// 前一個節點對象        /// </summary>        public MyLinkedNode<T> Prev { get; internal set; }        /// <summary>        /// 後一個節點對象        /// </summary>        public MyLinkedNode<T> Next { get; internal set; }    }

     2.接下來,在封裝一個對節點的操作的操作類,正好複習 迭代器yield和理解IEnumerable<T>這個介面,時間有限,這裡我只先實現AddLast和GetEnumerator

 //接下來,因為鏈式結構,只適合從尾部和首部增加元素,中間不方便增加元素。所以對節點的操作的封裝類,一般 首部增加一個節點AddFirst(),尾部增加一個節點AddEnd()    //移除一個節點RemoveFirst(),RemoveEnd(),這裡我只先實現AddEnd和GetEnumerator    public class MyLinkedList<T> : IEnumerable<T>    {        /// <summary>        /// 預設 IEnumerable定義的,必須實現        /// </summary>        /// <returns></returns>        public IEnumerator<T> GetEnumerator()        {            //使用yield,把MyLinkedNode<T>返回到IEnumerator中去            MyLinkedNode<T> cur = First;            while (cur!=null)    //如果下一個節點不為空白            {                yield return cur.Value;                cur = cur.Next;//把當前值設定成下一個節點的值            }        }        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()        {            return GetEnumerator();        }        /// <summary>        /// 添加一個節點,預設都是從尾部增加的        /// </summary>        /// <param name="myLinkedNode">MyLinkedNode中類型的值</param>        /// <returns></returns>        public MyLinkedNode<T> AddEnd(T myLinkedNode)        {            MyLinkedNode<T> cur = new MyLinkedNode<T>(myLinkedNode);            if (First == null)            {                  //如果該集合一個節點也沒有,那麼第一個和最後一個節點就等於當前節點                First = End = cur;            }            else {              //因為尾部新節點增加,原來上次的尾部的節點就變成了該節點的前一個節點了,他自己變成了最後一個節點                MyLinkedNode<T> prevEnd = End;                //更新新的最後一個元素                End.Prev = prevEnd;                End.Next = cur;                End = cur;            }            return cur;        }        //在鏈式結構裡面都有 第一個節點和最後一個節點的特殊節點        /// <summary>        /// MyLinkedList集合中第一個元素        /// </summary>        public MyLinkedNode<T> First { get; private set; }        /// <summary>        /// MyLinkedList集合中最後一個元素        /// </summary>        public MyLinkedNode<T> End { get; private set; }        /// <summary>        /// 在開始的地方增加一個節點        /// </summary>        /// <param name="myLinkedNode">MyLinkedNode值</param>        /// <returns></returns>        public MyLinkedNode<T> AddFirst(T myLinkedNode)        {            throw new NotImplementedException();//自己實現        }        /// <summary>        /// 移除一個節點        /// </summary>        /// <param name="myLinkedNode">MyLinkedNode對象</param>        /// <returns></returns>        public MyLinkedNode<T> RemoveEnd(T myLinkedNode)        {            throw new NotImplementedException();//自己實現        }    }

       3.使用這個資料結構的集合

 class Program    {        static void Main(string[] args)        {            MyLinkedList<int> m = new MyLinkedList<int>();            m.AddEnd(1);            m.AddEnd(10);            m.AddEnd(100);            foreach (var item in m)            {                Console.WriteLine(item+",");            }            Console.ReadLine();        }    }

效果

 整個過程來說,感覺還是挺有意義的,特別當泛型的概念融入其中,你的代碼可能更精彩。

 1.4 一些資料結構的類型,只是加深印象: Queue<T>,Dictionary<TKey, TValue>, ILookup(TKey, TElement) 等

 1.5 泛型預設值初始化,舉個例子      public T GetT(){ T t=default(T);  ...     }

 1.6 泛型約束與繼承:

       public abstract class Class1<T> :TEnumerable<T>

       public class DBManager<TDb> where TDb:ICommonDb,new()

       Aaronyang拓展: where T:struct / class  / 介面  / new() 建構函式約束,指定類型T必須有一個預設建構函式 /  其他泛型,例如  where T1:T2

 *1.7 靜態成員:AaronYang講解:只要記得 T 不一樣,裡面的靜態成員的值是不共用的,也不會受影響。   專業術語:泛型類的靜態成員只能在類的一個執行個體中共用

      自己寫了一個例子,一看就懂了

 class Program    {        static void Main(string[] args)        {            OwnStaticGeneric1<string>.obj = 4;            OwnStaticGeneric1<int>.obj = 5;            OwnStaticGeneric1<string>.obj = 6;            OwnStaticGeneric1<int>.obj = 7;            Console.WriteLine(OwnStaticGeneric1<string>.obj);//   =>6            Console.WriteLine(OwnStaticGeneric1<int>.obj); // =>7            OwnStaticGeneric2<string>.obj = "4";            OwnStaticGeneric2<int>.obj = 5;            OwnStaticGeneric2<string>.obj = "6";            OwnStaticGeneric2<int>.obj = 7;            Console.WriteLine(OwnStaticGeneric1<string>.obj);//   =>6            Console.WriteLine(OwnStaticGeneric1<int>.obj); // =>7            Console.ReadLine();        }    }    public class OwnStaticGeneric1<T> {        public static int obj;    }    public class OwnStaticGeneric2<T>    {        public static T obj;    }

 1.8 進階知識: 泛型介面,感覺讓你考架構師的樣子

    1.8.1  拓展一下 可能會使用的 跟 ref和out差不多性質的  in(in修飾的參數,在方法體內的過程不會改寫in的參數的值)關鍵字用法。如果不太懂,可以百度,也可以看我下面的例子,但提前,你最好懂out,ref的基礎用法。

              有些人設計介面直接    IInterface<T1,T2>,其實也還有很奇妙的其他寫法,用 in或者out或者ref 修飾泛型的情境

          講解: 一個SubClass類實現了ITestIn介面,out定義輸出類型,in定義輸入類型,必須是把值輸入,所以莫名的 ITestIn<string,object> 一下子就懂了。還不懂的話,建議你百度

          留個題目:如何 讓使用者寫代碼可以寫出如下的效果,Student的值是不允許改變的,請設計介面

          public class Student:ICustomComparable<Student>{

                public int CompareTo(Student stu){

                    return ... ;

                }

          }

          參考部分答案(答案字型被我設定成白色了,查看的,自己選擇後面的空白部分): public interface ICustomComparable<in T>{     int    CompareTo(T stu);   }

            

     1.8.2  其實上面的 in或者out修飾泛型,涉及到了泛型知識中的 協變(泛型參數被out修飾)與抗變(泛型參數被in修飾)的知識,不要太在意,會用就好!!!!!!oh! shit,抗英(國)

 

1.9 Nullable<T>      T必須是實值型別,定義可為空白,有興趣的可以看看 public struct Nullable<T> where T:struct的實現

      等同寫法:       Nullable<int>    a   等同於  int? a

      ?? 的用法: 例如 int y=x ?? 0;   如果x為null,則等於0,否則就是原值。

1.10 當然泛型也可以像用在類上那樣用於方法上,這個知識太簡單,不講了

1.11 泛型委派,Lambda運算式最多,典型的有比如Func  Action等,這些在LINQ裡再講

1.12 作為一年以上的開發人員,都知道的我都跳過了,可能存在疑問的地方保留了。

 

 

 

======安徽六安=========www.ayjs.net==========aaronyang========楊洋==================

 

[AaronYang]C#人愛學不學[4]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.