Dans l'exemple de code suivant, nous avons une classe pour les objets immuables qui représente une pièce. Le nord, le sud, l'est et l'ouest représentent des sorties dans d'autres pièces.
public sealed class Room
{
public Room(string name, Room northExit, Room southExit, Room eastExit, Room westExit)
{
this.Name = name;
this.North = northExit;
this.South = southExit;
this.East = eastExit;
this.West = westExit;
}
public string Name { get; }
public Room North { get; }
public Room South { get; }
public Room East { get; }
public Room West { get; }
}
On voit donc que cette classe est conçue avec une référence circulaire réflexive. Mais parce que la classe est immuable, je suis coincé avec un problème de «poulet ou d'oeuf». Je suis certain que les programmeurs fonctionnels expérimentés savent comment gérer cela. Comment le gérer en C #?
J'essaie de coder un jeu d'aventure basé sur du texte, mais en utilisant des principes de programmation fonctionnels juste pour le plaisir d'apprendre. Je suis coincé sur ce concept et je peux utiliser de l'aide !!! Merci.
MISE À JOUR:
Voici une implémentation fonctionnelle basée sur la réponse de Mike Nakis concernant l'initialisation paresseuse:
using System;
public sealed class Room
{
private readonly Func<Room> north;
private readonly Func<Room> south;
private readonly Func<Room> east;
private readonly Func<Room> west;
public Room(
string name,
Func<Room> northExit = null,
Func<Room> southExit = null,
Func<Room> eastExit = null,
Func<Room> westExit = null)
{
this.Name = name;
var dummyDelegate = new Func<Room>(() => { return null; });
this.north = northExit ?? dummyDelegate;
this.south = southExit ?? dummyDelegate;
this.east = eastExit ?? dummyDelegate;
this.west = westExit ?? dummyDelegate;
}
public string Name { get; }
public override string ToString()
{
return this.Name;
}
public Room North
{
get { return this.north(); }
}
public Room South
{
get { return this.south(); }
}
public Room East
{
get { return this.east(); }
}
public Room West
{
get { return this.west(); }
}
public static void Main(string[] args)
{
Room kitchen = null;
Room library = null;
kitchen = new Room(
name: "Kitchen",
northExit: () => library
);
library = new Room(
name: "Library",
southExit: () => kitchen
);
Console.WriteLine(
$"The {kitchen} has a northen exit that " +
$"leads to the {kitchen.North}.");
Console.WriteLine(
$"The {library} has a southern exit that " +
$"leads to the {library.South}.");
Console.ReadKey();
}
}
Room
exemple.
type List a = Nil | Cons of a * List a
. Et un arbre binaire: type Tree a = Leaf a | Cons of Tree a * Tree a
. Comme vous pouvez le voir, ils sont tous deux auto-référentiels (récursifs). Voici comment vous définissez votre chambre: type Room = Nil | Open of {name: string, south: Room, east: Room, north: Room, west: Room}
.
Room
classe et celle de a List
sont similaires dans le Haskell que j'ai écrit ci-dessus.