title: How to get compile-time checking for value types in LINQ/lambdas/expression trees?
body: <p>I'm using the following code to set <code>Control</code> properties in a thread-safe manner:</p>
  
  <pre><code>private delegate void SetPropertyThreadSafeDelegate&lt;TPropertyType&gt;(Control @this, Expression&lt;Func&lt;TPropertyType&gt;&gt; property, TPropertyType value);
  
  public static void SetPropertyThreadSafe&lt;TPropertyType&gt;(this Control @this, Expression&lt;Func&lt;TPropertyType&gt;&gt; property, TPropertyType value)
  {
    var propertyInfo = (property.Body as MemberExpression ?? (property.Body as UnaryExpression).Operand as MemberExpression).Member as PropertyInfo;
  
    if (propertyInfo == null ||
        !propertyInfo.ReflectedType.IsAssignableFrom(@this.GetType()) ||
        @this.GetType().GetProperty(propertyInfo.Name, propertyInfo.PropertyType) == null)
    {
      throw new ArgumentException("The lambda expression 'property' must reference a valid property on this Control.");
    }
  
    if (propertyInfo.PropertyType.IsValueType &amp;&amp;
        !propertyInfo.PropertyType.IsAssignableFrom(typeof(TPropertyType)))
    {
      throw new ArgumentException(string.Format("Attempted to assign incompatible value type: expecting {0}, got {1}.", propertyInfo.PropertyType, typeof(TPropertyType)));
    }
  
    if (@this.InvokeRequired)
    {
      @this.Invoke(new SetPropertyThreadSafeDelegate&lt;TPropertyType&gt;(SetPropertyThreadSafe), new object[] { @this, property, value });
    }
    else
    {
      @this.GetType().InvokeMember(propertyInfo.Name, BindingFlags.SetProperty, null, @this, new object[] { value });
    }
  }
  </code></pre>
  
  <p>It's called like so:</p>
  
  <pre><code>downloadProgressBar.SetPropertyThreadSafe(() =&gt; downloadProgressBar.Step, 32);
  </code></pre>
  
  <p>The reason for doing this is to get compile-time checking of property names and type assignments. It works perfectly for standard objects, but everything goes a bit pear-shaped with value types because the compiler is happy to accept the following, which of course bombs at runtime:</p>
  
  <pre><code>downloadProgressBar.SetPropertyThreadSafe(() =&gt; downloadProgressBar.Step, 'c');
  downloadProgressBar.SetPropertyThreadSafe(() =&gt; downloadProgressBar.Step, long.MaxValue);
  </code></pre>
  
  <p>I've already modified the <code>SetPropertyThreadSafe</code> method to handle the case when value types are used, and throw an exception if the incorrect type is used as an argument, but what I'm really loooking for is the ability to get this method to perform compile-time type checking for 100% of cases, i.e. objects <em>and</em> value types. Is this even possible and if so how would I need to modify my code to do this?</p>