如何在没有类型参数的情况下调用Func?

时间:2014-04-28 17:35:09

标签: c# lambda func

请注意,我的逻辑是复杂的,我已经简化了一切,专注于这个问题。

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

我收到以下错误,

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

我尝试过的替代品,我已经知道了,我正在寻找更好的性能,然后是以下替代方案。

  1. 使用动态
  2. 重新创建表达式树,然后动态编译并执行
  3. 两种选择都非常昂贵,我需要更简单的方法。

    这不是我为什么会遇到这个编译器错误的问题,或者我是否需要重新设计我的应用程序,当我已经说过我有两个调用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";
        }
    
    }
    

2 个答案:

答案 0 :(得分:3)

你在这里尝试做的事情并没有多大意义。假设你有一个A类,以及两个继承它的B和C类。

如果你能够做你在这里说的话,那么使用函数Func<B, string>并将其转换为Func<A, string>意味着你得到的函数也可以将C的实例作为参数因为C也继承自A。

事实上,你可以更进一步说,因为所有东西都是从object继承的,你可以将任何函数转换为Func<object, string>,然后传入你想要的任何参数作为参数。

答案 1 :(得分:2)

让我们摆脱代表一秒钟,并根据他们抽象的方法来考虑这一点。请考虑以下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. 您知道编译器没有的东西,虽然编译器无法验证此约束是否正确,但实际上它在运行时无论出于何种原因都是有效的。由于您知道它不会失败,您可以使用强制转换通知编译器,并将类型检查推迟到运行时。

  3. 如果你碰巧在这里的第二个位置而不是第一个位置,你可以不通过强制转换委托来添加强制转换,而是通过创建一个新的方法(可能通过lambda)来对参数执行强制转换然后调用另一个代理:

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