這是使用經典的事件 - 一個方法調用自身的技術:
public static Filter CreateFilter(List<int> values) => values.Any() ? new Filter //If the list contains elements, create the filter
{
Value = values.First(), //assign the first item of the values to the value property
NextFilter = CreateFilter(values.Skip(1).ToList()) //Create the rest of the nested object with the rest of the values
} : null; //If there aren't any items left in the list, return null and stop the recursion
你當然可以做到這一點在構造函數,以及:
public Filter(List<int> values)
{
if (!values.Any()) return;
Value = values.First();
NextFilter = values.Count > 1 ? new Filter(values.Skip(1).ToList()) : null;
}
更多關於遞歸的信息,看看這個:https://www.dotnetperls.com/recursion,欲瞭解嵌套類的更多信息,請閱讀:https://www.dotnetperls.com/nested-class。
遞歸數的更多信息:
實際上,你可以實現通過遞歸的一切 - 你甚至不需要循環。這就是爲什麼像這樣的語言Haskell循環不存在的原因。 最簡單的遞歸函數是:
public static void EndlessLoop()
{
//Loop body
EndlessLoop();
}
然而,即使ReSharper的建議將其轉換爲一個循環:
另一個例子,如果你想獲得一個列表的總和,你可以這樣做:
public static int Sum(List<int> summands) => summands.Count > 0
? summands.First() + Sum(summands.Skip(1).ToList())
: 0;
但是這些例子在C#中沒有用,因爲C#不是一種函數式編程語言,它使遞歸比循環慢。此外,遞歸經常導致StackOverflowException(適合此網站)。如果你運行無限循環遞歸,它甚至不需要一秒鐘,直到你的堆棧已滿。
原因是,C#將從中調用方法的地址添加到堆棧。如果一個方法經常被調用(並且在1秒鐘內會產生大量的遞歸調用),那麼很多地址會被添加到堆棧中,以致它會溢出。
但我仍然認爲,即使這些示例在c#中沒有用處,它能夠處理遞歸非常有用。遞歸是例如探索的目錄結構,爲獲得例如所有文件的唯一方法:
public static List<FileInfo> GetAllFiles(DirectoryInfo directory) => directory.GetFiles()
.Concat(directory.GetDirectories().SelectMany(GetAllFiles))
.ToList();
而且,正如你經驗豐富,這是從列表填寫一個嵌套類正確的唯一途徑。