1

I have a class in a very basic C# console game (text adventure) that I would like to modify a variable elsewhere in the code. I understand that C# does not allow global variables, but that is essentially what I am looking for.

I am a beginner at programming. I am stumped and I've been unable to find an answer to this question. It's really a question of scope that I'm after; what variables can "talk" to each other. I'll include a simple example below.

All of these fields in the class will be modified elsewhere within various methods.

class Player        
{
    public int health = 100;
    public string armor = "none";
    public string gun = "none";
    public int money = 1000;
}

    public static void AddMoney()
{
    var NewPlayer = new Player();
    NewPlayer.money += 1500;
}

So I want to basically know what is expected of me to do if global variables aren't a thing in C#.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • 1
    Well, you showed that you are indeed able to change the public (aka global) variables using `NewPlayer.money`. So what's the problem? Are you looking for [static](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/static) members implementation? – 41686d6564 stands w. Palestine Jul 25 '19 at 02:32
  • Field variables shouldn't be public. Make them properties. – LarsTech Jul 25 '19 at 18:47
  • I'd recommend you read up about class constructors –  Jul 25 '19 at 18:51
  • In your own words, what is a class? What is an object? What is your existing understanding of how this works? – Karl Knechtel Jul 25 '19 at 19:06

2 Answers2

0

Disclaimer: you could make Player a static class, which would probably behave how you want, but doing so is ill-advised as it limits you to a single player object and can't easily be unit tested, amongst other problems. See When to use static classes in C#.

You have to understand that you Player is a class. Think of it as a blueprint for how a Player object should look. I usually go to a car analogy for this: you buy two Toyota Priuses. Identical in every way. You take one to a spray shop and have a design painted on it. Has the other Prius changed? No. It's the same with var player1 = new Player(); var player2 = new Player(); - they are both of type "Player", but they are not the same player.

Now consider your AddMoney method:

public static void AddMoney()
{
    var NewPlayer = new Player();
    NewPlayer.money += 1500;
}

You're creating a player that only exists within the AddMoney method. Once outside, it effectively doesn't exist anymore (stuff isn't deleted from memory immediately, but garbage collection isn't a topic you should be concerned with just yet).

Since Player is a class, it's a reference type, which means that passing it to a method will pass a reference to the same object in memory. This means that we can change the object in AddMoney and it will be reflected in the caller. Note that we can't replace the object - for that you would need the ref keyword (but that's another topic too).

public static void AddMoney(Player player)
{
    player.money += 1500;
}

Example:

var player = new Player();
player.money = 8500;
Console.WriteLine(player.money); // 8 500
AddMoney(player);
Console.WriteLine(player.money); // 10 000

Try it online

Alternatively, if you want to create a player, you could create a factory method:

public static Player CreatePlayer()
{
    return new Player
    {
        money = 1500
    };
}
ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
0

There's a few ways of updating instance variables in C#: Using properties or setters like in Java or instance methods. Following code shows you a few of those.

Ultimately, what you want to do is pass a reference to the instance of the player to different methods and let them use the properties/methods to update the instance variables:

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            var p1 = new Player();

            p1.Health = 5000;
            p1.Armor = "Helmet";
            p1.AddMoney(200);

            Console.WriteLine($"Health: { p1.Health }");

            var enemy = new Enemy();

            enemy.Shoot(p1);

            Console.WriteLine($"Health after being shot: {p1.Health}");
        }
    }

    class Player
    {
        private string armor;
        private int money;

        public int Health { get; set; }

        public string Armor
        {
            get => armor;
            set
            {
                Console.WriteLine("Updating armor.");
                armor = value;
            }
        }

        public int Money { get; private set; }

        public void AddMoney(int money)
        {
            // More complex logic here, example: synchronization.
            this.money = money;
        }
    }

    class Enemy
    {
        public void Shoot(Player p)
        {
            p.Health -= 500;
        }
    }
}

This is the object-oriented way of doing things. As for global variables in the sense of application-wide variables, you can refer to this.

You can also make the Player a singleton. This is more a design choice than actual C# stuff. I'm not going to go into singleton pattern here. If you search singletons and their pros and cons, you will get an earful of that :)

kovac
  • 4,945
  • 9
  • 47
  • 90