将Func <t,object =“”>转换为Func <frameworkelement,object =“”>

时间:2015-12-10 15:07:01

标签: c# generics

我有两个班级:

class Model
{
    //...
    public Func<FrameworkElement , object> Property { get; set; }
    //...
}

class Other
{
    public void MyMethod<T>(Type type, Func<T, object> selector) where T : FrameworkElement
    {
        this.MyList.Add(new Model() { Property = selector  });
    }    
}

我有一个错误:Impossible to convert Func<T,object> to Func<FrameworkElement,object>

当我尝试:

var tmp = selector as Func<FrameworkElement, object>

tmp的值为null

为什么我使用这样的方法签名? 因为该方法将被调用,而我无法预测框架元素是什么,例如:

myVar.MyMethod<TextBox>(t=>t.Text) ; 

myVar.MyMethod<Label>(t=>t.Content) ;

1 个答案:

答案 0 :(得分:0)

如上所述here

  

函数功能&LT; T,TResult&gt;,具有协变返回类型和逆变   参数类型。

这意味着T参数可以是一个&#34;较少的派生类&#34;。

因此,如果您执行以下操作,则可以使用:

public class MyFrameworkElement { }
public class MyTextBox : MyFrameworkElement { }

class Program 
{    
        public static Object MyMethod(MyFrameworkElement b) 
        {
            return new Object();
        }

        static void Main(string[] args) 
        {

            Func<MyFrameworkElement, Object> f1 = MyMethod;
            Func<MyTextBox, Object> f2 = f1;
       }
}

如您所见,您可以指定一个Func&lt; MyFrameworkElement,Object&gt;到一个Func&lt; MyTextBox,Object&gt;,因为第一个参数是逆变的(你可以指定&#34;较少的派生类型&#34;在这种情况下MyFrameworkElement指向MyTextBox)。

就像我说的那样,类型参数是逆变的而不是协变的,所以它反过来不起作用!

像这样:

class Program 
{    
    public static Object MyMethod2(MyTextBox b) 
    {
            return new Object();
    }

    static void Main(string[] args) 
    { 
        Func<MyTextBox, Object> f3 = MyMethod2;

        //This does not compile, and with cast you cannot make this work either.
        Func<MyFrameworkElement, Object> f4 = f3;  // as Func<MyFrameworkElement, Object>; <- does not help
    }
}

这是有道理的,因为MyMethod2有一个MyTextBox参数,而f4会指向MyFrameworkElement。 MyTextBox可以有一个你可以在MyMethod2中访问的Text属性,但是使用f4你会传递一个没有该属性的MyFrameworkElement。

不幸的是,你要做的是第二种情况。