【发布时间】:2020-08-23 19:41:05
【问题描述】:
我在Predicate<T> 中转换内部类型时遇到以下问题。我有一个实现基本接口的类。除了接口之外,该类还有一些高级属性和方法。
public interface IBasic { /* ... */ }
public class Advanced : IBasic { /* ... */ }
在一个方法中,我在 Advanced 类上获得了许多谓词,我想将它们分类到两个列表中:1) 仅使用 IBasic 接口的谓词 2) 需要来自 @ 的所有功能的谓词987654328@班级。
List<Predicate<IBasic>> basic = new List<Predicate<IBasic>>();
List<Predicate<Advanced>> advanced = new List<Predicate<Advanced>>();
public void SetPredicates(params Predicate<Advanced>[] predicates)
{
foreach(var item in predicates)
{
//Of course the `is` keyword does not work here, always returning false.
//Is it possible to do the check on the lambda function in item in a different way?
if (item is Predicate<IBasic>)
basic.Add((Predicate<IBasic>)item); //And this cast throws an exception of course.
else
advanced.Add(item);
}
}
问题
- 有可能吗?
- 如何检查谓词的泛型类型是否可以简化为
IBasic接口? - 如何执行谓词转换?
谓词的数量很少,所以我可以使用较慢的东西,例如 dynamic 类型的反射。
背景
谓词分区的原因是我有很多Advanced 实例。我想首先通过只需要 IBasic 接口的谓词对它们进行预过滤,因为它们的评估速度非常快。然后我将不得不在第二遍中使用Advanced 的复杂方法(不在IBasic 中)过滤更少数量的实例,因为它们需要很长时间来评估。
【问题讨论】:
-
这似乎完全破坏了Liskov Substitution Principle。在我看来,设计出了点问题,现在你有一个XY problem
-
@CamiloTerevinto 谢谢你的建议。我不知道它会如何破坏它。换个角度看,如果你找到更好的设计,请告诉我:我有类
Advanced具有各种属性。有些属性评估很快,但有些需要很长时间。我有很多Advanced实例要检查,每个实例都需要遵守一些谓词。我希望首先使用快速谓词对它们进行预过滤。为了确定哪些谓词是 fast 的,我将 fast 属性提取到IBasic接口,现在我正在尝试进行类型检查和强制转换。 -
@PavelAnikhouski 谢谢!是的,我正在尝试在运行时进行逆变泛型转换。根据我从文章中的理解,如果我在 lambda 主体上进行强制转换,它可以工作,例如
SetPredicates((IBasic b) => b.Count > 1 )但我无法控制如何调用该方法。我将尝试将其分为两种方法,看看是否有帮助,尽管设计更差。
标签: c# foreach casting type-conversion