Question

Assigning an Integer to a double is very much legal.

If we can do

double d = 3;

d is assigned 3.0

but why this fails in Attached Properties?

Scenario

I created an Attached Property

public static readonly DependencyProperty ActualWidthBeforeHidingProperty = 
       DependencyProperty.RegisterAttached("ActualWidthBeforeHiding", 
       typeof(double), typeof(MainWindow), new FrameworkPropertyMetadata(0));

public static double GetActualWidthBeforeHiding(DependencyObject element)
    {
        if (element == null)
        {
            throw new ArgumentNullException("element");
        }

        return Convert.ToDouble(element.GetValue(ActualWidthBeforeHidingProperty));
    }

public static void SetActualWidthBeforeHiding(DependencyObject element, double value)
    {
        if (element == null)
        {
            throw new ArgumentNullException("element");
        }

        element.SetValue(ActualWidthBeforeHidingProperty, value);
    }

I compiled the code. There was no compiletime error.

But when I tried to run the application it gave error

enter image description here

In the above code I accidently assigned 0 in new FrameworkPropertyMetadata(0) and the code ran successfully.

But I was under the impression that you can assign a DataType having lesser precision (i.e. Integer) to a DataType having greater precision (i.e. 0.0 Double)?

Then Why this deflection from basic programming concept for Dependency Properties?

Was it helpful?

Solution 2

This is because of boxing:

The parameter of the FrameworkPropertyMetadata constructor is declared as object, so when you do new FrameworkPropertyMetadata(0), the integer value 0 is boxed to an object (because int is a value type). When WPF tries to use this default value, it tries to unbox it to a double (since the property is declared as double), which fails because the boxed value is an int, not a double. A boxed value can only be unboxed to its actual type, the usual implicit numeric conversions (like int to double) don't work in this case.

Here's an example that illustrates the problem:

int i = 42;
double d1 = i; // Works fine, uses the built-in conversion from int to double
object o = i; // boxing
double d2 = (double)o; // Fails: unboxing to the wrong type

The compiler doesn't know statically that the object is actually a boxed int, so it can't use the built-in conversion; all it can do is unbox the value to the type specified by the developer.

OTHER TIPS

You are not doing a (simple) assignment. The default value is stored as a reference (boxed int) and later the property tries to get the default value as the specified type (double). In short, this code is equivalent :

 object x = 1;          // boxed int
 double d = (double)x;  // InvalidCast exception

The solution is of course simple:

 object x = 1.0;        // boxed double
 double d = (double)x;  // OK
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top