Reputation: 174
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
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
Reputation: 13525
add field this0=this and in the setter, check that this==this0.
Upvotes: -1
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
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