如何在不带类型参数的情况下调用Func

本文关键字:情况下 调用 Func 类型参数 | 更新日期: 2023-09-27 18:00:39

请注意,我的逻辑太复杂了,我简化了所有内容来关注这个问题。

我有函数字典,我必须调用它,但Function将类型T作为输入参数,这是派生类型,我没有访问权限,在运行时可以是任何类型。我该如何调用它?

我收到以下错误,

Unable to cast object of type 
 'System.Func`2[DerivedClass,System.String]' to type    
 'System.Func`2[BaseClass,System.String]'.

我已经尝试过并且已经知道的替代方案,我正在寻找比以下替代方案更好的性能。

  1. 使用动态
  2. 重新创建表达式树,然后动态编译和执行

这两种选择都非常昂贵,我需要更简单的方法。

这不是关于我为什么会出现这个编译器错误,或者我是否需要重新设计我的应用程序的问题,当我已经说过我有两个调用Func的替代方案时,我正在寻找第三个更简单的替代方案(如果存在)

如何在没有DerivedClass访问权限的情况下调用Func<DerivedClass,String>?我随身携带一件物品。

class Program
{
    static void Main(string[] args)
    {
        object input = new DerivedClass();
        Func<BaseClass, string> f = null;
        Func<DerivedClass, string> a = s => s.ToString();
        object obj = a;
        // ERROR
        f = (Func<BaseClass, string>)obj;
        Console.WriteLine(f(input));
        Console.ReadLine();
    }
}

public class BaseClass {
    public override string ToString()
    {
        return "Base Class";
    }
}
public class DerivedClass : BaseClass {
    public override string ToString()
    {
        return "Derived Class";
    }
}

如何在不带类型参数的情况下调用Func

您在这里试图做的事情实际上没有意义。假设您有一个类a,以及从中继承的两个类B和C

如果你能做到这里所说的,那么取一个函数Func<B, string>并将其转换为Func<A, string>就意味着你得到了一个函数,它也可以取C的一个实例作为参数,因为C也继承自a。

事实上,您可以更深入地说,由于所有内容都是从对象继承的,所以您可以将任何函数强制转换为Func<object, string>,然后将您想要的任何内容作为参数传入。

让我们暂时摆脱委托,并根据它们正在抽象的方法来考虑这一点。考虑以下Foo方法:

public static void Foo(int i)
{
    Console.WriteLine(i + 2);
}

现在我们有了另一种方法Bar。它接受object。我们想对参数调用Foo

public static void Bar(object o)
{
    Foo(o);
}

当然,这是行不通的。我们无法知道所提供的对象实际上是一个int

这通常意味着两件事之一:

  1. 你实际上并不想这样做;你无法知道更通用的参数实际上是正确的更派生的参数的实例;你应该重新设计你的应用程序。

  2. 你知道编译器不知道的一些东西,虽然编译器无法验证这个约束是正确的,但无论出于什么原因,它在运行时都是有效的。由于您知道它不会失败,因此可以使用强制转换通知编译器这一点,并将类型检查推迟到运行时。

如果您恰好处于第二个位置,而不是第一个位置,则可以不通过强制转换委托来添加强制转换,而是通过创建一个新方法(可能通过lambda)来对参数执行强制转换,然后调用另一个委托:

Func<DerivedClass, string> derivedSelector = derived => derived.ToString();
Func<BaseClass, string> baseSelector = s => derivedSelector((DerivedClass)s);