1. 程式人生 > >WPF依賴屬性(續)(1)

WPF依賴屬性(續)(1)

原文: WPF依賴屬性(續)(1)

      
         之前有寫過幾篇文章,詳細地介紹了依賴屬性的基本使用方法,如果你不想了解其內部實現機制的話,那麼通過那兩篇文章的介紹,足以應付平時的應用了.關於其內部實現,部落格園的周永恆也有人詳細介紹過,還原了依賴屬性的實現.通過閱讀後和閱讀原始碼併為了加深理解,下面則繼續依賴屬性的探討.

屬性記憶體問題

如下程式碼,Name有一個預設的空字串,Test1方法添加了10000個物件,那麼在沒有改變People 的Name屬性情況下,同時也建立了10000個空字串

public class People
{
    private string _name="";
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

public class EntityTest
{
    public void Test1()
    {
        List<People> list=new List<People>();
        for (int i = 0; i < 10000; i++)
        {
            list.Add(new 
People()); } } }

問題
:本一個預設值可以解決的問題,卻用了10000個物件去解決,浪費了記憶體.
思路:為屬性建立一個預設值

建立屬性預設值

將_name欄位改為靜態
private static string _name="";
問題:雖然引用同一個記憶體,但當任意修改一個物件的Name屬性時,則全部發生了變更.
思路:提供預設值,如屬性值發生變更,則使用修改的值,但不影響其他物件
程式碼改進如下
public class People
{
    private static string _name="";

    private static 
Dictionary<object, string> list = new Dictionary<object, string>(); public string Name { get { if (list.ContainsKey(this.GetHashCode())) return list[this.GetHashCode()]; return _name; } set { list[this.GetHashCode()] = value; } } }
測試程式碼
public static void Test2()
{
    List<People> list = new List<People>();
    for (int i = 0; i < 10000; i++)
    {
        var entity = new People();
        if (i<10)
        {
            entity.Name = i.ToString();
        }
        list.Add(entity);
    }
}

image

依賴物件共享依賴屬性

下面我們來看下WPF元素的依賴屬性,我們可以來比較下兩個不同物件的屬性元資料,返回的結果是相同,也說明了其內部機制也是如此,也是為了節省記憶體.

Object.ReferenceEquals(Button.BackgroundProperty.GetMetadata(button1),
                       Button.BackgroundProperty.GetMetadata(button2));

比較兩個物件的屬性,依然是相同,因為返回的是預設值

Object.ReferenceEquals(button1.Background, button2.Background);

然而為了節省記憶體,真的有必要這麼做嗎?這太麻煩了.

我們知道WPF控制元件繼承而來的屬性有一大片,密密麻麻,當我們佈局的的時候窗體上往往有著很多的元素,如下截圖.如果一個物件以50個屬性(其實遠遠不止)來計算,那麼也是一筆不小的開銷,如果說依賴屬性一開始的動機是為了節省記憶體,實質上其內部功能已經遠遠不是節省記憶體這麼簡單了.下篇繼續

image