Вы также можете использовать это. Отметьте Building
как класс вместо Buildings
. Отделите здания от города и внедрите их с помощью конструктора:
Кроме того, ваш int i = 0; i++
имеет ошибки и может вызвать IndexOutOfRangeException .
public class Town
{
private List<Building> buildings;
private List<string> buildingNames = new List<string>() {"Town_Hall", "Market", "Residences", "Mortician", "Bank", "Hotel", "Tailor", "Gunsmith", "General_Store", "Sheriff", "Well", "Gate", "Wall"};
public Town(List<Building> buildings)
{
this.buildings = buildings;
}
public void ResetTown()
{
int i = 0;
foreach (Building building in buildings)
{
building.Name = buildingNames[i].ToString();
building.Level = 0;
i++;
}
}
public IEnumerator<Building> GetEnumerator()
{
return buildings.GetEnumerator();
}
}
public class Building
{
public string Name {get; set;}
public int Level {get; set;}
}
Вложенные функции являются отличным способом разделить работу на многие функции. Это не действительно "сторона-effecty"; если это помогает, думайте о полученных переменных как о неявных параметрах.
Один пример, где вложенные функции полезны, состоит в том, чтобы заменить циклы. Параметры к вложенной функции могут действовать как индукционные переменные, которые накапливают значения. Простой пример:
let factorial n =
let rec facHelper p n =
if n = 1 then p else facHelper (p*n) (n-1)
in
facHelper 1 n
В этом случае действительно не имело бы смысла объявлять функцию как facHelper
глобально, так как пользователям не придется волноваться о p
параметр.
Знайте, однако, что может быть трудно протестировать вложенные функции индивидуально, так как они не могут быть упомянуты за пределами их родителя.
Функциональное программирование не является бескомпромиссным. Если бы вложение, функции имеют больше смысла, я пошел бы с тем подходом. Однако, Если Вы действительно хотите, чтобы внутренние функции были чисто функциональны, явно передайте все необходимые параметры в них.
Вот немного примера в Схеме:
(define (foo a)
(define (bar b)
(+ a b)) ; getting a from outer scope, not purely functional
(bar 3))
(define (foo a)
(define (bar a b)
(+ a b)) ; getting a from function parameters, purely functional
(bar a 3))
(define (bar a b) ; since this is purely functional, we can remove it from its
(+ a b)) ; environment and it still works
(define (foo a)
(bar a 3))
Лично, я пошел бы с первым подходом, но любой будет работать одинаково хорошо.
Рассмотрите следующий (изобретенный) отрывок Haskell:
putLines :: [String] -> IO ()
putLines lines = putStr string
where string = concat lines
string
локально связанная именованная константа. Но не это также функция, берущая аргументы, который закрывается lines
и поэтому соотносимо intransparent? (В Haskell константы и функции nullary действительно неразличимы!) Вы считали бы вышеупомянутый код “стороной-effecty” или нефункциональный из-за этого?