編寫高品質代碼改善C#程式的157個建議——建議23:避免將List<T>作為自訂集合類的基類

來源:互聯網
上載者:User

標籤:

建議23:避免將List<T>作為自訂集合類的基類

如果要實現一個自訂的集合類,不應該以一個FCL集合類為基類,反而應擴充相應的泛型介面。FCL結合類應該以組合的形式包含至自訂的集合類,需要擴充的泛型介面通常是IEnumerable<T>和ICollection<T>(或ICollection<T>的子介面,如IList<T>),前者規範了集合類的迭代功能,後者規範了一個集合通常會有的操作。

一般的情況下,下面兩個實現的集合類都能完成預設的需求:

class Employees1 : List<Employee>class Employees2 : IEnumerable<Employee>, ICollection<Employee>

不過,List<T>基本上沒有提供可供子類使用的protected成員(從object中繼承的Finalize和MemberwiseClone方法除外),所以繼承List<T>並沒有帶來任何繼承上的優勢,反而喪失了面向介面編程的靈活性。稍加不注意,隱含的Bug就會接踵而至。

以Employees1為例,如果要在Add方法中加入某些需求方面的變化,比如,為名字添加一個尾碼“Changed!",但是用戶端的開發人員也許已經習慣了面向介面編程的方式,他在為集合添加一個元素是使用了如下的文法:

        static void Main(string[] args)        {            Employees1 employees1 = new Employees1()             {                new Employee(){ Name = "Mike" },                new Employee(){ Name = "Rose" }            };            IList<Employee> employees = employees1;            employees.Add(new Employee() { Name = "Steve" });            foreach (var item in employees1)            {                Console.WriteLine(item.Name);            }        }        class Employee        {            public string Name { get; set; }        }        class Employees1 : List<Employee>        {            public new void Add(Employee item)            {                item.Name += " Changed!";                base.Add(item);            }        }

於是,代碼的實際輸出會偏離集合類設計者的設想。代碼輸出為:

Mike Changed!
Rose Changed!
Steve

要糾正這類行為,應該採用Employees2的方式:

        static void Main(string[] args)        {            Employees2 employees2 = new Employees2()             {                new Employee(){ Name = "Mike" },                new Employee(){ Name = "Rose" }            };            ICollection<Employee> employees = employees2;            employees.Add(new Employee() { Name = "Steve" });            foreach (var item in employees2)            {                Console.WriteLine(item.Name);            }        }        class Employees2 : IEnumerable<Employee>, ICollection<Employee>        {            List<Employee> items = new List<Employee>();            #region IEnumerable<Employee> 成員            public IEnumerator<Employee> GetEnumerator()            {                return items.GetEnumerator();            }            #endregion            #region ICollection<Employee> 成員            public void Add(Employee item)            {                item.Name += " Changed!";                items.Add(item);            }            //省略            #endregion        }

輸出結果為:

Mike Changed!
Rose Changed!
Steve Changed!

 

 

轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技

編寫高品質代碼改善C#程式的157個建議——建議23:避免將List<T>作為自訂集合類的基類

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.