代码改变世界

WPF依赖属性(续)(1)

2010-06-11 13:06  Clingingboy  阅读(4935)  评论(12编辑  收藏  举报

      
         之前有写过几篇文章,详细地介绍了依赖属性的基本使用方法,如果你不想了解其内部实现机制的话,那么通过那两篇文章的介绍,足以应付平时的应用了.关于其内部实现,博客园的周永恒也有人详细介绍过,还原了依赖属性的实现.通过阅读后和阅读源代码并为了加深理解,下面则继续依赖属性的探讨.

属性内存问题

如下代码,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