C# 如何解决 Func<T, bool> 中的逆变问题?
C# how to workaround contravariance in Func<T, bool>?
假设我有以下代码:
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 作为派生的比 object.
有办法绕过它吗?从我的角度来看,之后做这样的事情是完全正确的:
foreach (var e in GetExclusions<PropertyInfo>())
{
var a = members.Where(e);
}
在提出任何建议之前,当前的设计很可能不适合您需要解决的问题。所以我真的建议只要有机会就重新访问它
现在回答你的问题,一种选择是将对象转换为 lambda 中的预期类型;
像这样:
Func<object, bool> l = o => lambda((T) o);
然后您可以在 Dictionary<Type, Func<object, bool>>
中跟踪每种不同 Type
的表达式类型。如果您不想保留字典,可能还有其他选择,但它们会涉及使用包含相同信息的 class
实际上,只在 List<object>
中存储 lambda 似乎更方便,在这种情况下,您不需要来回转换 Func<T, bool>
的参数,只需转换 lambda 本身> :
List<object> _exclusions = new List<object>();
public IEnumerable<Func<T, bool>> GetExclusions<T>()
{
return _exclusions.OfType<Func<T, bool>>();
}
假设我有以下代码:
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 作为派生的比 object.
有办法绕过它吗?从我的角度来看,之后做这样的事情是完全正确的:
foreach (var e in GetExclusions<PropertyInfo>())
{
var a = members.Where(e);
}
在提出任何建议之前,当前的设计很可能不适合您需要解决的问题。所以我真的建议只要有机会就重新访问它
现在回答你的问题,一种选择是将对象转换为 lambda 中的预期类型; 像这样:
Func<object, bool> l = o => lambda((T) o);
然后您可以在 Dictionary<Type, Func<object, bool>>
中跟踪每种不同 Type
的表达式类型。如果您不想保留字典,可能还有其他选择,但它们会涉及使用包含相同信息的 class
实际上,只在 List<object>
中存储 lambda 似乎更方便,在这种情况下,您不需要来回转换 Func<T, bool>
的参数,只需转换 lambda 本身> :
List<object> _exclusions = new List<object>();
public IEnumerable<Func<T, bool>> GetExclusions<T>()
{
return _exclusions.OfType<Func<T, bool>>();
}