9

I read this in the following link:-

http://www.informit.com/articles/article.aspx?p=688529&seqNum=2

However, because GetValue and SetValue internally use an efficient sparse storage system and because IsDefaultProperty is a static field (rather than an instance field), the dependency property implementation saves per-instance memory compared to a typical .NET property. If all the properties on WPF controls were wrappers around instance fields (as most .NET properties are), they would consume a significant amount of memory because of all the local data attached to each instance.

But eventually they are getting stored somewhere, how does it saves memory consumption ?

Tim Lloyd
  • 37,954
  • 10
  • 100
  • 130
teenup
  • 7,459
  • 13
  • 63
  • 122

2 Answers2

18

See the following link: Dependency Properties.

What is declared by an object as a dependency property is in fact nothing more than an identifier. This static "property" is really a key which associates an object with a specific storage identifier. For example graphical objects have a Background property that can be set explicitly or through the use of templates or styles..

As long as a Dependency Property uses its default state (which is very common), it won't take up any additional memory since the default value will be used. The default value isn't stored per instance, it is stored per Dependency Property and it's set by metadata.

Example, notice how Brushes.Black is set as the default value

public static readonly DependencyProperty ForegroundProperty =
    DependencyProperty.Register(
        "Foreground",
        typeof(Brush),
        typeof(TextElement),
        new FrameworkPropertyMetadata(Brushes.Black, ...));

Think of it this way: Say you have four TextBlocks in Xaml

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

The three TextBlocks at the top have Foreground set to Black although you have never explicitly set it to Black. They are using their default value. So for the Foreground property for the three TextBlocks above, you only need one field (since it is a static field).

For the forth TextBlock though, you have explicitly set Foreground to Green, so that value is inserted into a dictionary as the local value for Foreground on this instance and thus requires additional memory (also, it will end up at place number 3 in the list below, overriding Setters, Triggers etc).

Also, see the following post by Josh Smith, it's a good read: Demystifying dependency properties

There is a well-defined set of rules which is used internally by WPF to figure out what the real value of a DP is. Here is a brief summary of the rules of precedence used when resolving the value of a DP (read more about it here):

  1. Property system coercion
  2. Active animations, or animations with a Hold behavior
  3. Local value
  4. TemplatedParent template
  5. Style triggers
  6. Template triggers
  7. Style setters
  8. Theme style
  9. Inheritance
  10. Default value from dependency property metadata

Edit: To answer the comment from Duane

If you explicitly set the value to the same value as the default value, it will still get stored as the local value. This can easily be verified with the following Xaml.

Both TextBlocks will have Foreground set to Black, but the later has a local value set. The Style will only be able to set Foreground on the first TextBlock and not the later since Style setters has lower priority than local value.

<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>
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
Fredrik Hedblad
  • 83,499
  • 23
  • 264
  • 266
  • So, if you explicity set a proprty to the default value in xaml does it store that value independently, or does it rscognize it as the default and clear that instances entry? I'm wondering if this is another reason (other than clutted XAML) not to unnecessarily set properties to their default value. – Duane Aug 21 '11 at 13:07
  • @Duane: It stores that value as the local value even if it is the same as the default value. See my updated answer – Fredrik Hedblad Aug 21 '11 at 13:22
  • @Duane If if the DP property were overridden in the table, the use of Black is a reference to a static object that already exists in memory. So the cost would be an extra hashtable entry, but nothing more. Whether or not the DP system compares values to their original default value is a matter of internal optimization (time vs. space consideration). For instance, it could compare Black to Black and say "ah, this is the same as my default value" and just exclude the extra table entry in that case. But that comparison would take time - without looking at the code, it's hard to say. – cunningdave Aug 21 '11 at 14:31
  • Just to clarify, no such comparison exist, look at the last part of my answer. It isn't as simple as default value vs local value, there are other parts in the chain as well (style setters, triggers etc.). Setting a value sets a local value, no matter what the default value is. And as cunningdave said, the extra cost of an extra entry in a dictionary is nothing to worry about, if you look at the default template for e.g `ComboBox` then you'll see hundreds of them :) – Fredrik Hedblad Aug 21 '11 at 15:02
  • Thanks for the clarification. That was my assumption on how it worked. It still seems like setting a value to the default is something you would want to avoid (unless it was to override a style or something), especially on a large application where the difference could be noticed. I know it would be negligible on resources, but not everything is a resource, and the fact that you Re holding another dictionary entry ties up more memory and ultimately slows down that dictionaries lookup. – Duane Aug 22 '11 at 11:44
  • Even if the values are stored in a dictionary, still I can't understand how it saves memory. Because if it was stored in object directly, only a single storage space is required. But for storing in dictionary, an identifier (DP), the DP's value, and the owner object's reference - all three would be required. – teenup Sep 27 '13 at 06:18
  • @teenup: If you don't explicitly set the value, the value won't be stored in the dictionary. And if the value isn't in the dictionary, the default value will be used. That's where you save memory. – Fredrik Hedblad Sep 27 '13 at 07:04
  • Only in the case I use the default value, I understand that it will save memory, but if I set a value, then it needs 3 things to index in the dictionary - DP, DP's value, Owner object - am I right? In this case, isn't the consumption increases because in normal case the value will be saved directly inside the owner object? – teenup Sep 27 '13 at 07:22
  • @teenup: I'm not sure of the internal implementation in WPF but I think there is one Dictionary per DP. Also, you say "Only in the case I use the default value". A `TextBox`, for example, have something like 240 properties. How many properties do you usually set when you create an instance of a `TextBox`? 2-20? That means that the default value will be used for the other 238-220 properties. This is a greater value than an extra index in a `Dictionary` for the properties that you explicitly set. But as stated before, the cost of an extra entry in a dictionary is nothing to worry about – Fredrik Hedblad Sep 27 '13 at 08:48
  • 1
    I got it now. Thanks for your quick replies! – teenup Sep 27 '13 at 10:20
  • Wow. very nice explanation. Thanks. – Rohit Garg Dec 28 '16 at 06:51
8

First, suppose you create a class with a dozen properties. Create 100,000 of them. How many object references do you now have? 1,200,000.

Now implement a class called 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;
    }
}

Build a derived class like this:

public class MyDependencyObject : DependencyObject
{
    public SomeType Property1
    {
       get { return (SomeType)GetValue("Property1"); }
       set { SetValue("Property1", value]; }
    }

    // create 11 more properties like this
}

Now create 100,000 instances of MyDependencyObject and set their Parent. How many object references are used (not counting the parent)? 300,000.

That's how property value inheritance works in dependency objects.

Robert Rossney
  • 94,622
  • 24
  • 146
  • 218
  • +1 @Robert You answer gave me a perfect visualization of scenario. – teenup Aug 22 '11 at 08:19
  • Meleak's is a lot more exhaustive, but sometimes it just helps to look at a little code. This is yet another thing that Microsoft has done to shoehorn Python (which treats all class properties as dictionary entries) into C#. – Robert Rossney Aug 22 '11 at 08:25