0

private static field numberOfPlayersInOfflineGame has a property.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameData
{
    private static int numberOfPlayersInOfflineGame;

    int NumberOfPlayersInOfflineGame
    {
        get
        {
            return numberOfPlayersInOfflineGame;
        }
        set
        {
            numberOfPlayersInOfflineGame = value;
        }
    }
}

Here I'm trying to access the value of the above field from another class. But as you can see I cannot access it.

I'm using Visual Studio Community with Unity.

enter image description here

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Enzio
  • 799
  • 13
  • 32
  • 2
    Well no, you've made it private. The meaning of private is "you can't access it outside the program text of the declaring class". If you expected to be able to use the *property*, note that that isn't `static`, which is why you can't use it without an instance. (It's not clear that having an instance property backed by a static field is a good idea, mind you.) – Jon Skeet Mar 10 '18 at 07:22
  • 1
    Your property isn't public, and therefore can't be accessed publicly. – John Ilacqua Mar 10 '18 at 07:23
  • Possible duplicate of [What is the difference between Public, Private, Protected, and Nothing?](https://stackoverflow.com/questions/614818/what-is-the-difference-between-public-private-protected-and-nothing) – Tobias Theel Mar 10 '18 at 09:35

2 Answers2

7

That is the purpose of private fields - they cannot be accessed from other classes. But making the field public is not the way to go. Usually C# developers wrap the field in a public property, that can have validations o transformations implemented. This is almost what you did, you didn't explicitly make the property public, which is necessary.

The default member visibility is private so you should make your property public:

public class GameData
{
   private static int numberOfPlayersInOfflineGame;

   public static int NumberOfPlayersInOfflineGame
   {
      get
      {
         return numberOfPlayersInOfflineGame;
      }
      set
      {
         numberOfPlayersInOfflineGame = value;
      }
   }
}

But I am against what @Agent_Orange suggests: Do not make your field public as well! That completely defeats the purpose for creating a property. Any code could then bypass potential validations in the property setter to set the numberOfPlayersInOfflineGame to any unexpected value like -100.

As @Jon Skeet notes - if you don't perform any additional tasks in the getter and setter of the property, you could simplify your code by making it an auto-property:

public class GameData
{
   public static int NumberOfPlayersInOfflineGame { get; set; }
}

You can now use the property instead of the field both in your class code and outside of the class. If you later decide to add some validations, you can always go back to having a property backed by a private field.

Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91
  • 2
    As I noted in a comment on Agent_Orange's answer: if your property simply exposes the field in a trivial way, just us an automatically-implemented property. You can always go from that to a property with validation later on. – Jon Skeet Mar 10 '18 at 07:51
  • I know, I just wanted to keep the same form as the OP, so that it is clear that the property should be `public` while the field stays `private`. I will update my answer with this :-) – Martin Zikmund Mar 10 '18 at 07:53
  • 2
    Thank you for the explanation. I have done Java before so I assumed the default member visibility = "can be accessed from other classes in package". I didn't know it is private in C#. – Enzio Mar 10 '18 at 07:56
  • 2
    I'd like to add one thing though regarding Unity itself: if you use autoproperties, or a private field with a normal property, Unity won't serialize the field, so the variable will not be visible in the Inspector. So, the best way to use properties in Unity is to use a public property, a private field and tag the field with `[SerializeField]`. – Galandil Mar 10 '18 at 13:25
2

Answer


Private fields can only be accessed inside the class itself. To access it outside you would normally make it public or make a public method that returns the private variable.


Elaboration


Public, Private and more are what we call access modifiers.

The advantage of making a public getter method to a private variable, instead of making a public variable, is that you can control what happens as the variable is fetched.

In the section below I have quoted what the official documentation says about the different types of modifiers.

Access Modifiers (C# Programming Guide)

All types and type members have an accessibility level, which controls whether they can be used from other code in your assembly or other assemblies. You can use the following access modifiers to specify the accessibility of a type or member when you declare it:

public The type or member can be accessed by any other code in the same assembly or another assembly that references it.

private The type or member can be accessed only by code in the same class or struct.

protected The type or member can be accessed only by code in the same class, or in a class that is derived from that class. internal The type or member can be accessed by any code in the same assembly, but not from another assembly.

protected internal The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly.

private protected The type or member can be accessed only within its declaring assembly, by code in the same class or in a type that is derived from that class.

Source: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers

Doh09
  • 2,324
  • 1
  • 16
  • 31