这有两个部分。
首先,您需要调整NoFilter() 函数以兼容Predicate<T>。注意后者是通用的,但前者不是。使NoFilter() 看起来像这样:
private bool NoFilter<T>(T item) { return true; }
我知道您从不使用泛型类型参数,但有必要使其与您的谓词签名兼容。
为了好玩,你也可以这样定义NoFilter:
private Predicate<T> NoFilter = x => true;
现在是第二部分:我们可以看看使用新的泛型方法作为GetItems() 的默认参数。这里的诀窍是你只能使用 constants。虽然NoFilter() 永远不会改变,但从编译器的角度来看,这与形式常量并不完全相同。事实上,只有 一个 可能的常量可供您使用:null。这意味着您的方法签名必须如下所示:
private List<thing> GetItems(Predicate<thing> filter = null)
然后您可以在函数开头检查null并将其替换为NoFilter:
private List<thing> GetItems(Predicate<thing> filter = null)
{
if (filter == null) filter = NoFilter;
return rawList.Where(filter).ToList();
}
如果你还想在调用它时明确地将它传递给方法,那看起来像这样:
var result = GetItems(NoFilter);
这应该完全回答了最初的问题,但我不想停在这里。让我们更深入地了解一下。
由于您现在无论如何都需要if 条件,此时我倾向于完全删除NoFilter<T>() 方法,然后这样做:
private IEnumerable<thing> GetItems(Predicate<thing> filter = null)
{
if (filter == null) return rawList;
return rawList.Where(filter);
}
请注意,我还更改了返回类型并在最后删除了 ToList() 调用。如果您发现自己在函数末尾调用ToList() 只是为了匹配List<T> 返回类型,则几乎总是much 更好地将方法签名更改为返回IEnumerable<T>。如果你真的需要一个列表(通常你不需要),你可以在调用函数后随时调用ToList()。
此更改通过为您提供与其他接口更兼容的更抽象的类型,使您的方法更有用,并且它可能为您带来显着的性能提升,无论是在降低内存使用方面还是在惰性求值。
这里的最后一个补充是,如果你只削减到IEnumerable,我们现在可以看到,除了基本的rawItems 字段之外,这个方法并没有真正提供太多价值。您可能会考虑转换为属性,如下所示:
public IEnumerable<T> Items {get {return rawList;}}
这仍然允许您类型的消费者通过现有的.Where() 方法使用(或不使用)谓词,同时还继续隐藏底层原始数据(您不能直接调用.Add() 等关于这个)。