Estado del juego con diferentes estados y equatibilidad -- # campo con .net campo con comparative-review camp codereview Relacionados El problema

Game status with different states and equatability


1
vote

problema

Español

El estado de un juego puede ser:

  • funcionando, cuando aún no ha terminado,
  • corbata, cuando termine, pero ningún jugador ganó,
  • Win, cuando termine y un cierto jugador ganó.

Ser capaz de verificar la igualdad de estados que se desea.

Con estos en mente, codificé un 99887776655544330 Clase que implementa IEquatable :

  class GameStatus : IEquatable<GameStatus> {     public static GameStatus Running() => new GameStatus() { IsOver = false };     public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true };     public static GameStatus Win(Player winner) =>         new GameStatus() { IsOver = true, IsTie = false, Winner = winner };      public bool IsOver { get; private set; }     public bool IsTie { get; private set; }     public Player Winner { get; private set; }      public override bool Equals(object obj) => Equals(obj as GameStatus);     public bool Equals(GameStatus gs) {         return gs != null ?             (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) :             false;     }      public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner);      public static bool operator ==(GameStatus arg1, GameStatus arg2) =>         ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2);     public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2);      private GameStatus() { } }   

Uso del Player Enumeración y el HashHelper Clase:

  enum Player {     Red,     Black };  static class HashHelper {     public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3) {         unchecked {             return 103 * arg1.GetHashCode() + 31 * arg2.GetHashCode() + arg3.GetHashCode();         }     } }   

Un gamestatus se puede comparar con el Running , Tie , 9988776655544338 inmutables, o con otros estados. Anulación del Equals() , IEquatable0 y el IEquatable2 Los operadores aseguran que cada comparación debería ser correcta.


Sin embargo, había algo faltante.

Según la lógica empresarial, no tiene sentido preguntar si el estado es vinculado, cuando el juego se está ejecutando. Del mismo modo, no hay ningún punto pidiendo al ganador cuando el juego está funcionando o un empate. Por lo tanto, el IEquatable3 y IEquatable4 las propiedades tuvieron que ser modificadas:

  IEquatable5  

La clase de verificador:

  IEquatable6  

mis propios comentarios:

  • es IEquatable7 haciendo demasiado (es decir, Over-Engineering) Al verificar las propiedades?
  • Cualquier sugerencia para los nombres de IEquatable8 clase y IEquatable9 ?
  • los métodos class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 0 , class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 1 , class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 22 , Player23 y Player24 parece Para ser una placa de calderas que aparecerá en muchas clases. El único código de cambio es la lógica "Use los tres atributos class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 5 , class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 6 , class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 7 y mi tipo de clase".
  • class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 8 class GameStatus : IEquatable<GameStatus> { public static GameStatus Running() => new GameStatus() { IsOver = false }; public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true }; public static GameStatus Win(Player winner) => new GameStatus() { IsOver = true, IsTie = false, Winner = winner }; public bool IsOver { get; private set; } public bool IsTie { get; private set; } public Player Winner { get; private set; } public override bool Equals(object obj) => Equals(obj as GameStatus); public bool Equals(GameStatus gs) { return gs != null ? (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) : false; } public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner); public static bool operator ==(GameStatus arg1, GameStatus arg2) => ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2); private GameStatus() { } } 9655443329 Las clases parecen ser lo suficientemente simples, así que no para necesitar pruebas de unidad. ¿Estás de acuerdo?
Original en ingles

The status of a game can be:

  • running, when it is not over yet,
  • tie, when over but no player won,
  • win, when over and a certain player won.

Being able to check equality of statuses is desired.

With these in mind, I coded a GameStatus class which implements IEquatable:

class GameStatus : IEquatable<GameStatus> {     public static GameStatus Running() => new GameStatus() { IsOver = false };     public static GameStatus Tie() => new GameStatus() { IsOver = true, IsTie = true };     public static GameStatus Win(Player winner) =>         new GameStatus() { IsOver = true, IsTie = false, Winner = winner };      public bool IsOver { get; private set; }     public bool IsTie { get; private set; }     public Player Winner { get; private set; }      public override bool Equals(object obj) => Equals(obj as GameStatus);     public bool Equals(GameStatus gs) {         return gs != null ?             (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) :             false;     }      public override int GetHashCode() => HashHelper.GetHashCode(IsOver, IsTie, Winner);      public static bool operator ==(GameStatus arg1, GameStatus arg2) =>         ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2);     public static bool operator !=(GameStatus arg1, GameStatus arg2) => !(arg1 == arg2);      private GameStatus() { } } 

using the Player enumeration and the HashHelper class:

enum Player {     Red,     Black };  static class HashHelper {     public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3) {         unchecked {             return 103 * arg1.GetHashCode() + 31 * arg2.GetHashCode() + arg3.GetHashCode();         }     } } 

A GameStatus can be compared to the Running, Tie, Win(winner) immutables, or with other statuses. Overriding the Equals(), GetHashCode() and the == != operators assures that every comparison should be correct.


However, there was something missing.

According to the business logic, there is no point of asking whether status is tie, when the game is running. Similarly there is no point asking for the winner when the game is running or a tie. So the IsTie and Winner properties had to be modified:

class GameStatusStrict : IEquatable<GameStatusStrict> {     public static GameStatusStrict Running() => new GameStatusStrict() { _isOver = false };     public static GameStatusStrict Tie() => new GameStatusStrict() { _isOver = true, _isTie = true };     public static GameStatusStrict Win(Player winner) =>         new GameStatusStrict() { _isOver = true, _isTie = false, _winner = winner };      public bool IsOver => _isOver;     public bool IsTie {         get {             Checker.Check(nameof(IsOver), IsOver, true);             return _isTie;         }     }     public Player Winner {         get {             Checker.Check(nameof(IsOver), IsOver, true);             Checker.Check(nameof(IsTie), IsTie, false);             return _winner;         }     }      public override bool Equals(object obj) => Equals(obj as GameStatusStrict);     public bool Equals(GameStatusStrict gs) {         return gs != null ?             (_isOver == gs._isOver) && (_isTie == gs._isTie) && (_winner == gs._winner) :             false;     }      public override int GetHashCode() => HashHelper.GetHashCode(_isTie, _isTie, _winner);      public static bool operator ==(GameStatusStrict arg1, GameStatusStrict arg2) =>         ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2);     public static bool operator !=(GameStatusStrict arg1, GameStatusStrict arg2) => !(arg1 == arg2);      private bool _isOver;     private bool _isTie;     private Player _winner;      private GameStatusStrict() { } } 

The Checker class:

static class Checker {     public static void Check(string varName, bool value, bool expectedValue) {         if (value != expectedValue)             throw new InvalidOperationException(string.Format("{0} should be {1}.", varName, expectedValue));     } } 

My own remarks:

  • Is GameStatusStrict doing too much (i.e. over-engineering) by checking on properties?
  • Any suggestions for the names of Checker class and Check()?
  • The methods Equals(object), Equals(GameStatus), GetHashCode(), operator ==() and operator !=() seem to be pretty much boilerplate that will appear in many classes. The only changing code is the logic "use all three attributes IsOver, IsTie, Winner and my class type".
  • GameStatus and GameStatusStrict classes seem to be simple enough so as not to need unit testing. Do you agree?
        
   
   

Lista de respuestas

2
 
vote

Lo que veo Akward desde el principio es que la clase está devolviendo las instancias del tipo de auto en los métodos estáticos como Running(), Tie() y 99887766555443311 . Esto es igual de método de encadenamiento, pero no está devolviendo la misma instancia, está devolviendo una nueva instancia, y se está accediendo estáticamente.

Espero que una clase de juego esté orientada a ser la huella digital de muchas instancias de juego. En el constructor de juegos, establecería las propiedades predeterminadas para un nuevo juego. (No es realmente necesario ya que el valor predeterminado de Enum en este caso se ejecutaría)

  public class Game() {   private Status status;   public Game() {     status = Status.Running;     } }   

El jugador es solo un enum que forma parte del resultado real. Así que me gustaría que, en el estado del juego. De lo contrario, si una clase expone a un booleano isOver Propiedad y un enum Winner Propiedad El caso predeterminado de estas propiedades es 9988776655544335 y también puede llevar a Las convinaciones no deseadas, como cuando se termina un partido y la vinculación no puede tener un ganador.

Por lo tanto, ya que los jugadores están destinados a indicar el resultado, haría que sea parte del establecimiento de estado.

  public Enum Status {   Running,   Tie,   RedWon,   BlackWon }   

Entonces, si necesita exponer las funciones para finalizar el juego, puede exponer Tie y Win que establecerá el estado interno de la clase.

  public class Game() {   private Status status = Status.Running;   public Tie() {     status = Status.Tie;   }   public RedWins() {     status = Status.RedWon;   }   public BlackWins() {      status = Status.BlackWon;   } }   

También puede pasar el estado a una función 99887766655443310 y cambiarla.

Para comparar dos juegos, puede compararlos utilizando la propiedad Estado.

Con el tiempo, si considera agregar más jugadores, deberá pensar en otra solución y establecer el estado para ser compuesto de la variable de jugador y el estado.

Hágame saber si eso ayuda, si la idea es usar realmente, tener estatus y jugadores por separado, podemos buscar otra forma de hacerlo.

 

What I see akward from the beggining is that the class is returning instances of the self type on static methods like Running(), Tie() and Win(Player winner). This is alike method chaining but not returning the same instance, it is returning a new instance, and its being accessed statically.

I would expect a Game class oriented to be the thumbprint of many Game instances. On Game constructor I would set the default properties for a new game. (Not really needed since default value of Enum in this case would be running)

public class Game() {   private Status status;   public Game() {     status = Status.Running;     } } 

The player is just an enum that is part of the actual result. So I would iclude that on the status of the game. Otherwise, if a class exposes an boolean isOver Property and an enum Winner Property the default case of this properties is isOver = false, winner = Player.Red and it also can lead to unwanted convinations, like when a match is over and tie cannot have a winner.

So since players are just meant to indicate the result I would make it be part of the status set.

public Enum Status {   Running,   Tie,   RedWon,   BlackWon } 

Then if you need to expose functions to end the game you can expose Tie and Win that will set the internal status of the class.

public class Game() {   private Status status = Status.Running;   public Tie() {     status = Status.Tie;   }   public RedWins() {     status = Status.RedWon;   }   public BlackWins() {      status = Status.BlackWon;   } } 

You also can just pass the status in to a SetStatus function and change it.

In order to compare two games you can just compare them by using the status property.

Over time if you consider adding more players you will need to think of another solution and set the status to be composite of player variable and status.

Let me know if that helps, if the idea is to really use IEquatable and have status and players separately we can look for another way of doing it.

 
 
   
   
1
 
vote

Intentaré asnwer el último Queiton, que es:

Las clases de Gamestatus y GamestAtusstrict parecen ser lo suficientemente simples para no necesitar pruebas de la unidad. ¿Estás de acuerdo?

No, no lo hago porque puede cometer errores fácilmente en el código que es demasiado obvio para probarlo . Aquí hay algunos ejemplos:

  Win(Player winner)1  

Esto es incorrecto porque devuelve Win(Player winner)2 Si alguno es 99887776655443313 . Debe devolverlo solo si ambos objetos son realmente iguales:

  Win(Player winner)4  

También en este método hay suficiente espacio para hacer que las cosas no funcionen correctamente:

  Win(Player winner)5  

Este no está equivocado per se, pero tampoco es una lógica simple. Un Win(Player winner)6 en el lugar equivocado y ya no funciona. Una prueba de unidad debe verificar que esto funciona como se esperaba.

En realidad, puedes simplificar este también. Usted no necesita los operadores de Ternarios aquí porque puede encadenar las expulsas con Win(Player winner)7

  Win(Player winner)8  

Un ejemplo más por qué debería probarlo ... porque ya lo haces con

  Win(Player winner)9  

Es tan simple que aparentemente ya no confíes en ti mismo y revise los valores de todos modos.

 

I'll try to asnwer the last quesiton which is:

GameStatus and GameStatusStrict classes seem to be simple enough so as not to need unit testing. Do you agree?

Nope, I don't because you can easily make mistakes in code that is too obvious to test it. Here are a few examples:

public static bool operator ==(GameStatusStrict arg1, GameStatusStrict arg2) =>     ReferenceEquals(arg1, null) ? ReferenceEquals(arg2, null) : arg1.Equals(arg2); 

This is wrong because it returns true if either object is null. It should return true only if both objects are really equal:

public static bool operator ==(GameStatusStrict arg1, GameStatusStrict arg2) =>     !ReferenceEquals(arg1, null) &&     !ReferenceEquals(arg2, null) &&     arg1.Equals(arg2); 

Also in this method there is enough room for making things not working correctly:

public bool Equals(GameStatus gs) {     return gs != null ?         (IsOver == gs.IsOver) && (IsTie == gs.IsTie) && (Winner == gs.Winner) :         false; } 

This one isn't wrong per se but it's not any simple logic either. One ! in the wrong place and it doesn't work anymore. A unit test should verify this works as expected.

Actually you can simplify this one too. You don't need the ternary operators here because you can just chain the experssions with &&

public bool Equals(GameStatusStrict gs) =>     gs != null &&     _isOver == gs._isOver &&     _isTie == gs._isTie &&      _winner == gs._winner; 

One more example why you should test it... because you already do it with

static class Checker {     public static void Check(string varName, bool value, bool expectedValue) {         if (value != expectedValue)             throw new InvalidOperationException(string.Format("{0} should be {1}.", varName, expectedValue));     } } 

It's so simple that you apparently don't trust yourself already and check the values anyway.

 
 
       
       
0
 
vote
vote
La mejor respuesta
 

Considerando los comentarios de Bruno , un enfoque de mantenimiento-it-simple es:

  public class Game() {   private Status status;   public Game() {     status = Status.Running;     } } 0  

Entonces, el estado puede ser ejecutado, vincularse o ganar. En caso de ganar, el ganador puede ser preguntado. Este enfoque no necesita una clase propia para el estado, puede simplemente estar en el interior del public class Game() { private Status status; public Game() { status = Status.Running; } } 1 .

El enfoque se puede simplificar adicionalmente eliminando el public class Game() { private Status status; public Game() { status = Status.Running; } } 22 MÉTODOS Y HACER LAS PROPIEDADES 99887776655443323 y isOver24 Públicamente configurable.

La desventaja es que la lógica "El ganador solo tiene sentido cuando hay una victoria" no se hace cumplir.

De hecho, regresar nuevas instancias y tratar de compararlas no tiene sentido. Sobrecomplica todo. Aunque no me gustó la idea de incluir a los jugadores en el public class Game() { private Status status; public Game() { status = Status.Running; } } 5 enumeración.

Recaudación de excepciones en una propiedad Getter es por cierto no recomendado. (Ahora lo sé. Q - :)

 

Considering the comments of Bruno, a keep-it-simple approach is:

enum Player {     Red,     Black };  enum GameStatus {     Running,     Tie,     Win };  class Game {     ...     public GameStatus Status { get; private set; }     public Player Winner { get; private set; }      public void SetRunning() => Status = GameStatus.Running;     public void SetTie() => Status = GameStatus.Tie;     public void SetWin(Player player) {         Status = GameStatus.Win;         Winner = player;     }      ... } 

So, the status can be running, tie, or win. In case of win, the winner can be enquired. This approach does not need a class of its own for the status, can as well simply lie inside the Game.

The approach can be further simplified by removing the Set... methods and making the properties Status and Winner publicly settable.

The disadvantage is that the logic "the winner only makes sense when there is a win" is not enforced.

Indeed, returning new instances and trying to compare them does not make sense. It overcomplicates everything. Though I didn't like the idea of including the players in the Status enumeration.

Raising exceptions in a property getter is BTW not recommended. (Now I know. q-:)

 
 
0
 
vote

Observaría que puede evitar tener que implementar Equals y GetHashCode e Operadores de igualdad si memobre todo. Me inclinaría a escribir tu clase así:

  abstract class GameStatus  {   private GameStatus() { } // No one else can create one.   private class TiedGame : GameStatus { ... }   public static readonly GameStatus Tied = new TiedGame();   private class RunningGame : GameStatus { ... }   public static readonly GameStatus Running = new RunningGame();   private class WonGame : GameStatus { ... }   private static Dictionary<Player, WonGame> d = new ...;   public static GameStatus Won(Player p)   {     WonGame w;     if (!d.TryGetValue(p, out w))     {         w = new WonGame(p);         d.Add(p, w);     }     return w;   }   ... abstract members, and so on ... }   

Ahora tiene la igualdad de referencia para cada diferente 9988776655544333 , por lo que no tiene que preocuparse por la implementación de la igualdad de valor.

 

I would note that you can avoid having to implement Equals and GetHashCode and equality operators if you memoize everything. I'd be inclined to write your class like this:

abstract class GameStatus  {   private GameStatus() { } // No one else can create one.   private class TiedGame : GameStatus { ... }   public static readonly GameStatus Tied = new TiedGame();   private class RunningGame : GameStatus { ... }   public static readonly GameStatus Running = new RunningGame();   private class WonGame : GameStatus { ... }   private static Dictionary<Player, WonGame> d = new ...;   public static GameStatus Won(Player p)   {     WonGame w;     if (!d.TryGetValue(p, out w))     {         w = new WonGame(p);         d.Add(p, w);     }     return w;   }   ... abstract members, and so on ... } 

Now you have reference equality for every different possible GameStatus, so you don't have to worry about implementing value equality.

 
 

Relacionados problema

5  Representando el tiempo de apertura y cierre para un negocio  ( Representing the opening and closing time for a business ) 
Tengo una clase de openclose que solo representa las horas de operación de un negocio por la apertura y el tiempo de cierre. Toma los tiempos de apertura y ci...

18  Invirtiendo una cadena  ( Reversing a string ) 
Tuve esto como una pregunta de entrevista, y el entrevistador señaló esto. Esto es lo que escribí: //C# Syntax here public string Reverse(string s) { c...

1  Configuración del camino a la barra de herramientasSociadaxIname, con retraso  ( Setting the path to toolbarassociatedxibname with fallback ) 
Tengo algún código que he incluido en un proyecto que quiero liberar. Aquí hay uno de esos bloques: NSString *path = nil; if (delegate && [delegate respond...

1  Visualización de Wuuks completados y fallidos usando una o dos funciones  ( Displaying completed and failed wuuks using one or two functions ) 
He actualizado mi código. En el código antiguo tuve dos funciones: display_maker_success()1 y display_maker_fail() : function display_maker_success($lin...

8  Contando novedades en un archivo  ( Counting newlines in a file ) 
He comenzado a pasar por tutoriales de nodos en nodoschool.io , y la segunda asignación fue escribir un programa que contará El número de nuevas líneas en un...

2  Formateo de un precio en SWIFT usando una extensión vs. una clase  ( Formatting a price in swift using an extension vs a class ) 
Tengo un precio como un Double , que debería formatearlo como un String . ¿Debo usar una extensión en lugar de clase clásica para encapsular "Formater", "...

2  Pasando funtores a algoritmos estándar  ( Passing functors to standard algorithms ) 
He creado 3 implementaciones diferentes (que producen los mismos resultados) utilizando la función en3 de STL. Deseo verificar la cantidad de elementos en e...

2  Validación instantánea de la longitud del campo de la forma  ( Instantaneous validation of form field length ) 
Dado que tengo una función que se puede hacer de unas maneras como de costumbre, me preguntaba qué sigue es el mejor para lograr la validación del formulario ...

2  Dos formas de aleatorias aleatoriamente las tarjetas  ( Two ways to randomly shuffle cards ) 
Aquí hay dos implementaciones que escribí para aleatorizar las tarjetas. El primer método ( dt5 ) Selecciona una tarjeta aleatoria, luego lo quita al frent...

3  Imitando la mensajería de la célula T9  ( Mimicking t9 cell messaging ) 
Hoy resolví una pregunta de Google Code Jam: imitando un teléfono celular de mensajería. Aquí está el programa, con goto Sé que es un estilo no estructura...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos