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
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?
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.