程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則17:裝箱和拆箱的最小化(3)

Effective C#原則17:裝箱和拆箱的最小化(3)

編輯:關於C語言

Person是一個值類型數據,在存儲到ArrayList之前它被裝箱 。這會產生一個拷貝。而在移出的Persone對象上通過訪問屬性做一些修改時, 另一個拷貝被創建。而你所做的修改只是針對的拷貝,而實際上還有第三個拷貝 通過ToString()方法來訪問attendees[0]中的對象。

正因為這以及其它 一些原因,你應該創建一些恆定的值類型(參見原則7)。如果你非要在集合中使 用可變的值類型,那就使用System.Array類,它是類型安全的。

如果一 個數組不是一個合理的集合,以C#1.x中你可以通過使用接口來修正這個錯誤。 盡量選擇一些接口而不是公共的方法,來訪問箱子的內部去修改數據:

public interface IPersonName
{
 string Name
 {
  get; set;
 }
}
struct Person : IPersonName
{
 private string _Name;
 public string Name
 {
  get
  {
   return _Name;
   }
  set
  {
   _Name = value;
  }
 }
 public override string ToString( )
 {
  return _Name;
 }
}
// Using the Person in a collection:
ArrayList attendees = new ArrayList( );
Person p = new Person( "Old Name" );
attendees.Add( p ); // box
// Try to change the name:
// Use the interface, not the type.
// No Unbox needed
(( IPersonName )attendees[ 0 ] ).Name = "New Name";
// Writes "New Name":
Console.WriteLine(
 attendees[ 0 ].ToString( )); // unbox

裝箱後的引用類型會實現原數據類型上所有已經實現的接 口。這就是說,不用做拷貝,你可以通過調用箱子上的IPersonaName.Name方法 來直接訪問請求到箱子內部的值類型數據。在值類型上創建的接口可以讓你訪問 集合裡的箱子的內部,從而直接修改它的值。在值類型上實現的接口並沒有讓值 類型成為多態的,這又會引入裝箱的懲罰(參見原則20)。

在C#2.0中對泛 型簡介中,很多限制已經做了修改(參見原則49)。泛型接口和泛型集合會時同處 理好集合與接口的困境。在那之前,我們還是要避免裝箱。是的,值類型可以轉 化為System.Object或者其它任何的接口引用。這些轉化是隱式的,使得發現它 們成為繁雜的工作。這些也就是環境和語言的規則,裝箱與拆箱操作會在你不經 意時做一些對象的拷貝,這會產生一些BUG。同樣,把值類型多樣化處理會對性 能有所損失。時刻注意那些把值類型轉化成System.Object或者接口類型的地方 :把值類型放到集合裡,調用定義參數為System.Object類型的方法,或者強制 轉化為System.Object。能夠避免就盡量避免!

返回教程目錄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved