转换函数<;T、 对象>;到Func<;FrameworkElement,对象>;

本文关键字:对象 gt lt Func FrameworkElement 函数 转换 | 更新日期: 2023-09-27 18:26:27

我有两个类:

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的值是CCD_ 2。

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

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

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

转换函数<;T、 对象>;到Func<;FrameworkElement,对象>;

如上所述:

Func<TTResult>,具有协变返回类型和逆变参数类型。

这意味着T参数可以是一个"派生程度较低的类"。

因此,如果你做以下操作,它是有效的:

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<MyFrameworkElement,Object>到Func<MyTextBox,Object>,因为第一个参数是反变量的(在这种情况下,您可以将"派生较少的类型"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可以有一个Text属性,您可以在MyMethod2中访问该属性,但使用f4,您将传递一个没有该属性的MyFrameworkElement。

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