如何在不带类型参数的情况下调用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]'.
我已经尝试过并且已经知道的替代方案,我正在寻找比以下替代方案更好的性能。
- 使用动态
- 重新创建表达式树,然后动态编译和执行
这两种选择都非常昂贵,我需要更简单的方法。
这不是关于我为什么会出现这个编译器错误,或者我是否需要重新设计我的应用程序的问题,当我已经说过我有两个调用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";
}
}
您在这里试图做的事情实际上没有意义。假设您有一个类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
。
这通常意味着两件事之一:
你实际上并不想这样做;你无法知道更通用的参数实际上是正确的更派生的参数的实例;你应该重新设计你的应用程序。
你知道编译器不知道的一些东西,虽然编译器无法验证这个约束是正确的,但无论出于什么原因,它在运行时都是有效的。由于您知道它不会失败,因此可以使用强制转换通知编译器这一点,并将类型检查推迟到运行时。
如果您恰好处于第二个位置,而不是第一个位置,则可以不通过强制转换委托来添加强制转换,而是通过创建一个新方法(可能通过lambda)来对参数执行强制转换,然后调用另一个委托:
Func<DerivedClass, string> derivedSelector = derived => derived.ToString();
Func<BaseClass, string> baseSelector = s => derivedSelector((DerivedClass)s);