簡體   English   中英

如何將謂詞作為參數c#傳遞

[英]How to pass a predicate as parameter c#

我如何將謂詞傳遞給方法,但如果沒有傳遞謂詞,它還可以工作嗎? 我想也許是這樣的,但它似乎不正確。

private bool NoFilter() { return true; }

private List<thing> GetItems(Predicate<thing> filter = new Predicate<thing>(NoFilter))
{
    return rawList.Where(filter).ToList();
}
private List<thing> GetItems(Func<thing, bool> filter = null)
{
    return rawList.Where(filter ?? (s => true)).ToList();
}

在此表達式中, s => true是回退過濾器,如果參數filter為null,則對其進行評估。 它只需要列表的每個條目(作為s )並返回true

這有兩個部分。

首先,您需要調整NoFilter()函數以與Predicate<T>兼容。 注意后者是通用的,但前者不是。 使NoFilter()看起來像這樣:

private bool NoFilter<T>(T item) { return true; }

我知道你從不使用泛型類型參數,但有必要使它與謂詞簽名兼容。

為了好玩,你也可以這樣定義NoFilter

private Predicate<T> NoFilter = x => true;

現在是第二部分:我們可以看一下使用新的泛型方法作為GetItems()的默認參數。 這里的訣竅是你只能使用常量 雖然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條件, if我傾向於完全刪除NoFilter<T>()方法,只需這樣做:

private IEnumerable<thing> GetItems(Predicate<thing> filter = null)
{
    if (filter == null) return rawList;
    return rawList.Where(filter);
}

請注意,我還更改了返回類型並在結尾處刪除了ToList()調用。 如果你發現自己在調用ToList()在函數結束只是為了匹配List<T>返回類型,它幾乎總是更好的改變方法簽名返回IEnumerable<T>代替。 如果你真的需要一個列表(通常你不需要),你可以在調用函數后調用ToList()

這種更改使您的方法更有用,為您提供一種更抽象的類型,與其他接口更兼容,並且它可能會在降低內存使用和延遲評估方面為您帶來顯着的性能提升。

這里最后一個補充是,如果你只關注IEnumerable ,我們現在可以看到這個方法在基礎rawItems字段之外並沒有提供太多的價值。 您可能會看到轉換為屬性,如下所示:

public IEnumerable<T> Items {get {return rawList;}}

這仍然允許您的類型的使用者通過現有的.Where()方法使用謂詞(或不使用.Where() ,同時還繼續隱藏基礎原始數據(您不能直接調用.Add()等這個)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM