WPF依赖属性设计如何节省内存消耗?

WPF依赖属性设计如何节省内存消耗?,wpf,dependency-properties,Wpf,Dependency Properties,我在下面的链接中读到了这一点:- 但是,由于GetValue和SetValue在内部使用高效的稀疏存储系统,并且IsDefaultProperty是一个静态字段(而不是实例字段),因此与典型的.NET属性相比,dependency属性实现节省了每个实例的内存。如果WPF控件上的所有属性都是围绕实例字段的包装器(与大多数.NET属性一样),那么它们将消耗大量内存,因为所有本地数据都附加到每个实例上 但最终它们会被存储到某个地方,如何节省内存消耗?请参阅以下链接: 对象声明为依赖属性的内容实际上是

我在下面的链接中读到了这一点:-

但是,由于GetValue和SetValue在内部使用高效的稀疏存储系统,并且IsDefaultProperty是一个静态字段(而不是实例字段),因此与典型的.NET属性相比,dependency属性实现节省了每个实例的内存。如果WPF控件上的所有属性都是围绕实例字段的包装器(与大多数.NET属性一样),那么它们将消耗大量内存,因为所有本地数据都附加到每个实例上

但最终它们会被存储到某个地方,如何节省内存消耗?

请参阅以下链接:

对象声明为依赖属性的内容实际上是 只不过是一个标识符。这个静态“属性”实际上是一个 将对象与特定存储标识符关联的键。对于 示例图形对象具有可设置的背景属性 明确地或通过使用模板或样式

只要依赖项属性使用其默认状态(这是非常常见的),它就不会占用任何额外的内存,因为将使用默认值。默认值不是按实例存储的,而是按依赖项属性存储的,由元数据设置

例如,请注意如何将
笔刷.Black
设置为默认值

这样想:假设您在Xaml中有四个
TextBlocks

<StackPanel>
    <TextBlock .../>
    <TextBlock .../>
    <TextBlock .../>
    <TextBlock Foreground="Green" .../>
</StackPanel>

首先,假设您创建了一个具有十几个属性的类。创造100000个。您现在有多少个对象引用?120万

现在实现一个名为
DependencyObject
的类:

public class DependencyObject
{
    public DependencyObject()
    {
       LocalValues = new Dictionary<string, object>();
    }

    protected Dictionary<string, object> LocalValues { get; set; }

    public DependencyObject Parent { get; set; }

    protected object GetValue(string propertyName)
    {
       if (LocalValues.ContainsKey(propertyName))
       {
          return LocalValues[propertyName];
       }
       return Parent.GetValue(propertyName);
    }

    protected void SetValue(string propertyName, object value)
    {
       LocalValues[propertyName] = value;
    }
}
现在创建100000个
MyDependencyObject
实例,并设置它们的
父对象。使用了多少对象引用(不包括父对象)?三十万


这就是属性值继承在依赖项对象中的工作方式。

因此,如果在xaml中明确地将属性设置为默认值,它是独立存储该值,还是将其识别为默认值并清除该实例条目?我想知道这是否是不必要地将属性设置为默认值的另一个原因(CLUTED XAML除外)。@Duane:它将该值存储为本地值,即使它与默认值相同。查看我的更新answer@Duane如果在表中重写了DP属性,则使用Black是对内存中已存在的静态对象的引用。因此,成本将是一个额外的哈希表条目,但仅此而已。DP系统是否将值与其原始默认值进行比较取决于内部优化(时间与空间考虑)。例如,它可以将黑色与黑色进行比较,并说“啊,这与我的默认值相同”,在这种情况下只排除额外的表项。但是这种比较需要时间——如果不看代码,很难说。为了澄清,不存在这种比较,请看我答案的最后一部分。它不像默认值和本地值那么简单,链中还有其他部分(样式设置器、触发器等)。设置值将设置本地值,无论默认值是什么。正如cunningdave所说,字典中一个额外条目的额外成本没什么好担心的,如果你查看默认模板,例如
ComboBox
,你会看到成百上千个:)我现在知道了。谢谢你的快速回复+1@Robert You answer给了我一个完美的场景可视化。Meleak的更详尽,但有时看一点代码会有所帮助。这是微软将Python(将所有类属性都视为字典条目)硬塞进C#的另一个做法。
<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="Green"/>
        </Style>
    </StackPanel.Resources>
    <TextBlock Text="Displays in Green"/>
    <TextBlock Foreground="Black" Text="Displays in Black"/>
</StackPanel>
public class DependencyObject
{
    public DependencyObject()
    {
       LocalValues = new Dictionary<string, object>();
    }

    protected Dictionary<string, object> LocalValues { get; set; }

    public DependencyObject Parent { get; set; }

    protected object GetValue(string propertyName)
    {
       if (LocalValues.ContainsKey(propertyName))
       {
          return LocalValues[propertyName];
       }
       return Parent.GetValue(propertyName);
    }

    protected void SetValue(string propertyName, object value)
    {
       LocalValues[propertyName] = value;
    }
}
public class MyDependencyObject : DependencyObject
{
    public SomeType Property1
    {
       get { return (SomeType)GetValue("Property1"); }
       set { SetValue("Property1", value]; }
    }

    // create 11 more properties like this
}