Quasar
Quasar

Reputation: 174

Can I prevent a private variable from being changed by other objects of the same class?

I'm multithreading a real-time game, and would like to prevent the state variables of objects on one thread from being set from another thread. This will make preventing race conditions a lot easier.

I would still like to be able to read the state of other objects, however. I'm intending to use a double buffer system, where one state object is used as the forebuffer and makes state changes while the other is used as the backbuffer and provides the (previous frame's) state to other objects. I need to be able to read state information from the backbuffer to make changes in the forebuffer.

The issue is that even if the variables setter is private, it's possible to change it from another object of the same class.

    public class State
    {
        //Some example state information
        public string StateVar1 { get; private set; }

        //This method will be farmed out to multiple other threads
        public void Update(State aDifferentStateObject)
        {
            StateVar1 = "I want to be able to do this";
            string infoFromAnotherObject = aDifferentStateObject.StateVar1; //I also want to be able to do this
            aDifferentStateObject.StateVar1 = "I don't want to be able to do this, but I can";
        }
    }

Upvotes: 0

Views: 1471

Answers (4)

TheGeneral
TheGeneral

Reputation: 81493

it's possible to change it from another object of the same class.

You cannot stop your own class from setting private setters.

I mean after all, you are the author of that class, its only your fingers you have to worry about.

public class SomeOtherNonRelatedClass
{
     public void Update(State aDifferentStateObject)
     {
        // the world is as it should be
        aDifferentStateObject.StateVar1 = "bang!!!" // compiler error
     }
}

If you would like to prevent your self from changing your own member, then use an extension method

public class Extensions
{
     public void Update(this State aDifferentStateObject)
     {
        // the world is as it should be
        aDifferentStateObject.StateVar1 = "bang!!!" // compiler error
     }
}

or make it truly read only (though is probably not useful)

public string StateVar1 { get; }

or a backing field, so you can set it internally

private string backingField;

public string StateVar1
{
    get => backingField;
}

Upvotes: 0

Alexei Kaigorodov
Alexei Kaigorodov

Reputation: 13525

add field this0=this and in the setter, check that this==this0.

Upvotes: -1

ShapeOfMatter
ShapeOfMatter

Reputation: 1011

If you're writing a class, it's assumed that you'll make the class work the way you want it to work. The purpose of making stuff private is to prevent your co-workers (or clients) from breaking your class's concerns while they work on their own classes/functions/modules.
Saying "I don't want to be able to do this thing." is somewhat missing the point.

That said, the thing that's nice about less permissive languages in general is that they prevent your co-workers from writing crappy or non-idiomatic code. The other answers show idioms you could use that would make it harder for your peers to later edit break your nice elegant pattern. Anu Viswan's get's my vote.

Upvotes: 0

Anu Viswan
Anu Viswan

Reputation: 18155

May not be the most direct solution, but one way to protect the properties is to use an interface.

public interface IState
{
    string StateVar1 { get; }
}

public class State:IState
{
    //Some example state information
    public string StateVar1 { get; private set; }

    //This method will be farmed out to multiple other threads
    public void Update(IState aDifferentStateObject)
    {
        StateVar1 = "I want to be able to do this";  // Allowed
        string infoFromAnotherObject = aDifferentStateObject.StateVar1; 
        aDifferentStateObject.StateVar1 = "I don't want to be able to do this, but I can"; // NOT allowed
    }
}

Upvotes: 2

Related Questions