关于WPF的属性系统园子内有不少这方面的文章。里面大都提到了WPF依赖属性的在内存方面的优化。但是里面大都一笔带过。那么WPF到底是怎么样节约内存的。我们通过WPF属性和普通的CLR属性对比来看一下WPF属性在节约内存方面的优势在哪里。

普通的CLR属性

public partial class WindowMemory : Window
{
  Student0 stu;
  public WindowMemory()
  {
    InitializeComponent();
    List<Student0> list = new List<Student0>();
    for (int i = ; i < ; i++)
    {
    stu = new Student0();
    list.Add(stu);
    }
  }
}
 public class Student0
{
public double Name { get; set; }
public double Name1 { get; set; }
public double Name2 { get; set; }
public double Name3 { get; set; }
public double Name4 { get; set; }
public double Name5 { get; set; }
public double Name6 { get; set; }
public double Name7 { get; set; }
public double Name8 { get; set; }
public double Name9 { get; set; }
public double Name10 { get; set; }
}

我们声明一个Student0类,里面放入十个属性。然后new 一千万个student 的实例加载到内存中。在任务管理器中看一下内存占用。

我们看到程序大概占用了一个G的内存。计算一下。因为c#中的属性是通过get set方法对一个私有字段的封装,也就是说这个类里面有十个double类型的私有字段。double类型占8个字节。一兆是1048576个字节,131072个double类型。一千万个double大概占用76兆的内存。我们这儿声明了十个也就是760兆。另外还有student对象占用的内存。所以这儿程序占用内存大概是一个G;

依赖属性

 public class Student0 : DependencyObject
{
public double Name
{
get
{
return (double)GetValue(NameProperty);
}
set
{
SetValue(NameProperty, value);
}
}
public double Name1
{
get
{
return (double)GetValue(Name1Property);
}
set
{
SetValue(Name1Property, value);
}
}
public double Name2
{
get
{
return (double)GetValue(Name2Property);
}
set
{
SetValue(Name2Property, value);
}
}
public double Name3
{
get
{
return (double)GetValue(Name3Property);
}
set
{
SetValue(Name3Property, value);
}
} public double Name4
{
get
{
return (double)GetValue(Name4Property);
}
set
{
SetValue(Name4Property, value);
}
}
public double Name5
{
get
{
return (double)GetValue(Name5Property);
}
set
{
SetValue(Name5Property, value);
}
}
public double Name6
{
get
{
return (double)GetValue(Name6Property);
}
set
{
SetValue(Name6Property, value);
}
} public double Name7
{
get
{
return (double)GetValue(Name7Property);
}
set
{
SetValue(Name7Property, value);
}
}
public double Name8
{
get
{
return (double)GetValue(Name8Property);
}
set
{
SetValue(Name8Property, value);
}
}
public double Name9
{
get
{
return (double)GetValue(Name9Property);
}
set
{
SetValue(Name9Property, value);
}
}
public double Name10
{
get
{
return (double)GetValue(Name10Property);
}
set
{
SetValue(Name10Property, value);
}
}public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name1Property = DependencyProperty.Register("Name1", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name2Property = DependencyProperty.Register("Name2", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name3Property = DependencyProperty.Register("Name3", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name4Property = DependencyProperty.Register("Name4", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name5Property = DependencyProperty.Register("Name5", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name6Property = DependencyProperty.Register("Name6", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name7Property = DependencyProperty.Register("Name7", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name8Property = DependencyProperty.Register("Name8", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name9Property = DependencyProperty.Register("Name9", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name10Property = DependencyProperty.Register("Name10", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
}

我们把student类修改为依赖对象,在里面实现十个依赖属性,此时来查看一下内存占用

此时只有三百多兆的内存占用。那么WPF的属性到底是如何节约内存的呢。因为CLR属性是在实例声明的时候就分配好了内存空间的。所以就算实例里面没有写入值,或者仍然是默认值,仍然会分配好内存空间。但是WPF的依赖属性不同。wpf的依赖属性是如下声明的

  public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
注意上面的这条语句才是依赖属性的声明。而类似下面这样的是我们通过clr属性对依赖属性NameProperty进行了包装,使我们访问起来更方便。就想普通的属性那样。
 public double Name
{
get
{
return (double)GetValue(NameProperty);
}
set
{
SetValue(NameProperty, value);
}
}

也就是说我们其实可以直接这样来声明Student0对象

  public class Student0 : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name1Property = DependencyProperty.Register("Name1", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name2Property = DependencyProperty.Register("Name2", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name3Property = DependencyProperty.Register("Name3", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name4Property = DependencyProperty.Register("Name4", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name5Property = DependencyProperty.Register("Name5", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name6Property = DependencyProperty.Register("Name6", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name7Property = DependencyProperty.Register("Name7", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name8Property = DependencyProperty.Register("Name8", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name9Property = DependencyProperty.Register("Name9", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
public static readonly DependencyProperty Name10Property = DependencyProperty.Register("Name10", typeof(double), typeof(Student0), new PropertyMetadata((double)55.55));
}

然后通过setvalue,getvalue来存取值

注意其实依赖属性的声明,在这里或者用注册来形容更贴切,只是一个入口点。也就是我们平常常说的单例模式。属性的值其实都放在依赖对象的一个哈希表里面。这里资料很多,大家随便找下就可以找到。

所以依赖属性正在节约内存就在于这儿的依赖属性是一个static readonly 属性。所以不需要在对象每次实例化的时候都分配相关属性的内存空间,而是提供一个入口点。

知道了这些我们再看一个没什么实际意义的例子。将student0对象修改如下。

  public class Student0
{
public double Name { get { return 1.00; } set { Name = 1.00; } }
public double Name1 { get { return 1.00; } set { Name1 = 1.00; } }
public double Name2 { get { return 1.00; } set { Name2 = 1.00; } }
public double Name3 { get { return 1.00; } set { Name3 = 1.00; } }
public double Name4 { get { return 1.00; } set { Name4 = 1.00; } }
public double Name5 { get { return 1.00; } set { Name5 = 1.00; } }
public double Name6 { get { return 1.00; } set { Name6 = 1.00; } }
public double Name7 { get { return 1.00; } set { Name7 = 1.00; } }
public double Name8 { get { return 1.00; } set { Name8 = 1.00; } }
public double Name9 { get { return 1.00; } set { Name9 = 1.00; } }
public double Name10 { get { return 1.00; } set { Name10 = 1.00; } }
}

此时程序只占用了不到200兆内存。因为属性的本质其实就是一个get set 方法。而方法是不需要实例化的,只需要一个指针指向就可以了。这儿我没没有在属性get;set;这种简化写法下声明的私有字段。所以没有了这些私有字段占用的内存。内存占用大大减少。

仔细对比我们就会发现。wpf的属性系统真的没有特别设计来优化内存。只是这种提供入口点的方式顺带就减少了内存的占用。

本文地址:http://www.cnblogs.com/santian/p/4372667.html

博客地址:http://www.cnblogs.com/santian/

转载请以超链接形式标明文章原始出处。

WPF 属性系统 依赖属性之内存占用分析的更多相关文章

  1. WPF教程:依赖属性

    一.什么是依赖属性 依赖属性就是一种自己可以没有值,并且可以通过绑定从其他数据源获取值.依赖属性可支持WPF中的样式设置.数据绑定.继承.动画及默认值. 将所有的属性都设置为依赖属性并不总是正确的解决 ...

  2. [No000012D]WPF(5/7)依赖属性

    介绍 WPF带来了很多传统 Windows 应用程序没有的新特性和选择.我们已经讨论了一些 WPF 的特性,是时候更进一步介绍其他特性了.当你读完这个系列之前的文章,我希望你已经或多或少地了解了 WP ...

  3. WPF属性(一)依赖属性

    原文:WPF属性(一)依赖属性 依赖属性是一种可以自己没有值,并能通过使用Binding从数据源获得值的属性,拥有依赖属性的对象称为依赖对象,在传统开发中,一个对象所占用的内存在调用new操作符进行实 ...

  4. WPF学习笔记——依赖属性(Dependency Property)

    1.什么是依赖属性 依赖属性是一种可以自己没有值,并且通过Binding从数据源获得值(依赖在别人身上)的属性,拥有依赖属性的对象被称为"依赖对象". 依赖项属性通过调用 Regi ...

  5. WPF 精修篇 依赖属性

    原文:WPF 精修篇 依赖属性 依赖属性使用场景 1. 希望可在样式中设置属性. 2. 希望属性支持数据绑定. 3. 希望可使用动态资源引用设置属性. 4. 希望从元素树中的父元素自动继承属性值. 5 ...

  6. WPF中的依赖属性

    1. WPF中的依赖属性 依赖属性是专门基于WPF创建的.在WPF库实现中,依赖属性使用普通的C#属性进行了包装,使用方法与普通的属性是相同的. 1.1 依赖属性提供的属性功能 资源 数据绑定 样式 ...

  7. (原创)2. WPF中的依赖属性之二

    1 依赖属性 1.1 依赖属性最终值的选用 WPF属性系统对依赖属性操作的基本步骤如下: 第一,确定Base Value,对同一个属性的赋值可能发生在很多地方.还用Button的宽度来进行举例,可能在 ...

  8. 【转】【WPF】关于依赖属性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的执行顺序

    三个回调对应依赖属性的验证过程,改变过程和强制转换过程. class Dobj : DependencyObject { //依赖属性包装 public int MyProperty { get { ...

  9. Unity3D–Texture图片空间和内存占用分析(转载)

    原地址:http://www.unity蛮牛.com/home.php?mod=space&uid=1801&do=blog&id=756 Texture图片空间和内存占用分析 ...

随机推荐

  1. 如何更专业的使用Chrome开发者工具

    顾名思义Chrome开发工具就是一个工具,它允许Web开发人员可以通过浏览器应用程序干预和操作Web页面,也可以通过这个工具调试和测试Web页面或Web应用程序.有了这个工具,你可以做很多有趣的事情: ...

  2. hbase集群安装和shell操作

    1.上传hbase安装包 2.解压 3.配置hbase集群,要修改3个文件(首先zk集群已经安装好了) 注意:要把hadoop的hdfs-site.xml和core-site.xml 放到hbase/ ...

  3. 奇怪也哉!做一个WebApp居然遇到了FF浏览器进不去某页的问题。

    一个小WebApp,原定login完后就进某页面.前天晚上之前一直在FF浏览器上调试,都正常. 前天晚上稍修改了,提交war上传,之后就休息了. 昨天晚上有些事情处理打开一看,乖乖,点登录后就在登陆页 ...

  4. Androidproject师进阶之路 :《Android开发进阶:从小工到专家》上市啦!

    封面 文件夹1 文件夹2 - 当当购买链接 - 京东购买链接 为什么写这本书 写这本书的念头由来已久了. 或许是从我打算写<Android源代码设计模式解析与实战>那时起就萌生了这个念头, ...

  5. jQuery--百度百科

    JQuery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, Oper ...

  6. import * as obj from 'xx'

    import * as obj from 'xx'  这种写法是把所有的输出包裹到obj对象里 例如: xx里中: export function hello(){ return '我是hello 内 ...

  7. PHP-Header缓存策略

    Expires.Cache-Control.Last-Modified.ETag 是RFC 2616(HTTP/1.1)协议中和网页缓存相关的几个字段.前两个用来控制缓存的失效日期,后两个用来验证网页 ...

  8. shell脚本与mongo交互

    1.mongo提供*.js的方法供linux调用 #!/bin/bash /usr/local/mongodb/bin/mongo hostname/dbname xxx.js xxx.js 内容如下 ...

  9. Retrofit2和RxJava配合使用Demo

    和Retrofit2单独使用有一些区别 首先,同样写个interface,这里是GitHubService.java,我们这次要实现获取官方提供的测试接口的数据 public interface Gi ...

  10. ImageBox Control with Zoom/Pan Capability

    Download source files - 10.8 Kb Download demo project - 6.81 Kb Introduction This control extends th ...