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); } }
依赖对象共享依赖属性
下面我们来看下WPF元素的依赖属性,我们可以来比较下两个不同对象的属性元数据,返回的结果是相同,也说明了其内部机制也是如此,也是为了节省内存.
Object.ReferenceEquals(Button.BackgroundProperty.GetMetadata(button1), Button.BackgroundProperty.GetMetadata(button2));
比较两个对象的属性,依然是相同,因为返回的是默认值
Object.ReferenceEquals(button1.Background, button2.Background);
然而为了节省内存,真的有必要这么做吗?这太麻烦了.
我们知道WPF控件继承而来的属性有一大片,密密麻麻,当我们布局的的时候窗体上往往有着很多的元素,如下截图.如果一个对象以50个属性(其实远远不止)来计算,那么也是一笔不小的开销,如果说依赖属性一开始的动机是为了节省内存,实质上其内部功能已经远远不是节省内存这么简单了.下篇继续