2017-08-29 67 views
2

我有Func<>具有泛型类作为输入参数。问题是如何将其转换为类似的Func,但是具有派生自前一个参数的类?现在下面的代码在fu2中给我null。Func与通用类参数和铸造

var fu = new Func<Envelope<Base>, object>(Simple); 
var fu2 = fu as Func<Envelope<Derived>, object>; 

public class Envelope<T> 
{ 
    public T Enveloped { get; set; } 
} 
public class Base 
{ 

} 
public class Derived: Base 
{ 

} 
+4

“FU2”似乎病命名,幸好C#编译器有厚的皮肤。也就是说,你不能做你想做的事。 'Envelope '在任何意义上都不是'Envelope '的子类;这是一个无关的班级。 –

回答

2

Func<T, object>T逆变所以

var fu2 = fu as Func<Envelope<Derived>, object>; 

如果Envelope<Derived>Envelope<Base>亚型会成功。类是不变的,但你可以定义一个接口:

public interface IEnvelope<out T> 
{ 
    T Enveloped { get; } 
} 

,并有Envelope<T>实现它。那么下面将编译:

Func<IEnvelope<Base>, object> fu = null; 
Func<IEnvelope<Derived>, object> fu2 = fu; 
1

铸造的一般表达式是不行的,因为lambda表达式之间不存在协方差。

但是,你就可以说构建了一个新的Envelope<Base>的表达,并封装包膜派生对象进去,就像这样:

var fu = new Func<Envelope<Base>,object>(Simple); 
Func<Envelope<Derived>,object> fu2 = x => fu(new Envelope<Base> {Enveloped = x.Enveloped}); 

新的表达式调用funew Envelope<Base> {Enveloped = x.Enveloped}参数,这是一个信封由fu2表达式的参数构造的兼容类型。

Demo.