3

In Haskell you can create a new datatype for example as follows:

Player = Player1 | Player2

And further in your code you can check whether it's Player1 or Player2 by just typing Player1 and not some strange with like "Player1" that it has to be a String or check with an integer. Is something similar possible in C#? I can only think of:

class Player
{
    public int CurrentPlayer { get; private set; }
    public Player(int plyr)
    {
        CurrentPlayer = plyr;
    }
}

But now I can't check with just thisplayer = Player1 (if thisplayer is a Player). Eventually this sort of means: How can you create your own object that can only have an already defined finite amount of values, for example like Bools?

  • These are called enums. – Tobias Kildetoft Oct 27 '20 at 16:11
  • nitpick: enums are just numbers, so you can give it a value outside of the "labeled" values, but you can always validate it – gunr2171 Oct 27 '20 at 16:12
  • You might consider C# [Enum](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/enum) – paulsm4 Oct 27 '20 at 16:14
  • https://stackoverflow.com/questions/3519429/what-is-main-use-of-enumeration – gunr2171 Oct 27 '20 at 16:16
  • Sadly popular OO languages lack good support for algebraic data types. I don't have any clue why. Scala is the only one I know of that makes a real attempt. – luqui Oct 27 '20 at 16:52
  • That particular data type you can model in C# as an `enum`. More generally, [sum types are isomorphic to the Visitor pattern](https://blog.ploeh.dk/2018/06/25/visitor-as-a-sum-type), – Mark Seemann Oct 27 '20 at 17:09
  • Are Player1 and Player2 different types of player (e.g. Wizard and Knight) or just two instances of the same type? – idz Oct 27 '20 at 19:54
  • @idz they are exactly the same they will just be used to distinguish whose turn it is and in which array i just modify elements – Joes de Jonge Oct 30 '20 at 20:38
  • @JoesdeJonge hmm, sounds like these arrays should belong to (be member variables of) the player class, no? – idz Oct 31 '20 at 06:49

2 Answers2

1

Use Enums:

using System;

public class Program
{
    private enum Player { PlayerOne, PlayerTwo }

    public static void Main()
    {
        Player player = Player.PlayerTwo; // Change me between Player.PlayerOne and Player.PlayerTwo to see the output change.
        switch(player)
        {
            case Player.PlayerOne:
                //this will get executed
                Console.WriteLine("Player is Player One!");
                //do stuff
                break;

            case Player.PlayerTwo:
                //this will not get executed
                Console.WriteLine("Player is Player Two!");
                //do stuff
                break;

            default:
                //this will not get executed
                break;
        }
    }
}

Output:

Player is Player Two!

See for yourself on .NET Fiddle

Hashgrammer
  • 155
  • 1
  • 5
0

Enums are a way to create a somewhat-strongly-typed set of aliases for integers. However, you can always cast an integer (of whatever type you specified for your enum, by default int) to the enum type, so you have to trust the code to not do that (which might be acceptable for an internal enum type). Additionally, you can't add any additional information to the enum value itself; any time you interpret the value, you have to use a switch or similar construct.

If you want to actually have a class with properties and such, but want to restrict the number of instances of that class, you can extend the singleton pattern like this:

sealed class Player
{
    // Properties that a Player object has, an improvement over using an enum
    // which don't allow you to specify properties.
    public int Number { get; }
    public bool IsHost { get; }

    // This constructor is private, so only the code inside the Player class may create a Player object
    // (notwithstanding reflection, etc., which are outside the rules of static typing).
    private Player(int number, bool isHost)
    {
        Number = number;
        IsHost = isHost;
    }
    
    // Static properties provide singleton instances of Player for each player number.
    public static Player One { get; }   = new Player(1, true);
    public static Player Two { get; }   = new Player(2, false);
    public static Player Three { get; } = new Player(3, false);
    public static Player Four { get; }  = new Player(4, false);
}

And then use it like this:

void Main()
{
    SomethingThatTakesPlayer(Player.Three);
}

void SomethingThatTakesPlayer(Player p)
{
    Console.WriteLine($"Player #{p.Number} is the host? {p.IsHost}");
}
Joe Sewell
  • 6,067
  • 1
  • 21
  • 34