C#如何解决Func <t,bool =“”>中的逆变问题?

时间:2015-09-18 10:12:04

标签: c# generics lambda casting contravariance

假设我有以下代码:

class Program
{
    static IList<Func<object, bool>> _exclusions = new List<Func<object, bool>>();

    static void Main(string[] args)
    {       
        SetExclusions<PropertyInfo>(x => typeof(ValueType).IsAssignableFrom(x.PropertyType));           
    }

    public static void SetExclusions<T>(Func<T, bool> lambda)
        where T : class
    {
        Func<object, bool> l = (Func<object, bool>)lambda; // <= InvalidCastException
        _exclusions.Add(l);
    }
}

当然它不起作用,因为Func中的 T 类型参数是逆变的 - 我不能传递 PropertyInfo ,因为它比对象

有没有办法绕过它?从我的观点来看,之后做这样的事情是完全正确的:

foreach (var e in GetExclusions<PropertyInfo>())
{
    var a = members.Where(e);    
}

2 个答案:

答案 0 :(得分:3)

在提出任何建议之前,当前的设计很可能不适合您需要解决的问题。所以我真的建议只要有机会就重新访问它

现在问题,一个选项可能是将对象转换为lambda内的预期类型; 像这样:

Func<object, bool> l = o => lambda((T) o); 

然后,您可以跟踪Dictionary<Type, Func<object, bool>>哪种类型的表达式适用于每个不同的Type。如果您不想保留字典,可能还有其他选择,但它们会涉及使用包含相同信息的类

答案 1 :(得分:0)

实际上,在List<object>中存储lambdas似乎更方便,在这种情况下,您不需要来回演变Func<T, bool>的参数,只是为了施放lambda本身&gt;:

List<object> _exclusions = new List<object>();
public IEnumerable<Func<T, bool>> GetExclusions<T>()
{
   return _exclusions.OfType<Func<T, bool>>();
}