0

I was trying to implement the state pattern in C#, and I did something like this:

class Context {
    private State state = null;
    private State concreteState1 = null;
    private State concreteState2 = null;

    public Context(State state) {
        concreteState1 = new ConcreteState1(this);
        ChangeStateTo(concreteState1);
    }

    public void ChangeStateTo(State state_) {
        state = state_;
    }

    public void DoSomething() {
        state.DoSomething();
    }

    public void DoSomethingElse() {
        state.DoSomethingElse();
    }
}
    
abstract class State {
    protected Context context;

    public void Context(Context context_) {
        context = context_;
    }

    public abstract void DoSomething();

    public abstract void DoSomethingElse();
}

Here, ConcreteState1 and ConcreteState2 are implementations of State that I omitted for brevity. The issue I'm having is that Context has some members that I would like all of the classes implementing State to access; I think this makes sense in the context of the pattern since the idea is for the context to act "as if" it was a different class depending on its state, and for this it would be useful for the states to be able to access its internals.

In C++ I would probably code this by setting State to be a friend class of Context, but since C# doesn't have anything similar to friend I'm not sure what to do here. I don't really want to create an assembly just for this specific finite state machine and put all the code in there. I also don't want a public setter for the private members of Context, because I don't want other classes modifying context. Is there any other good alternative that allows me to keep my Context and ConcreteState classes distinct but makes the internals of Context only available to State?

Ignacio
  • 377
  • 3
  • 12
  • 2
    You could consider making `State` a nested class within `Context`. I do something similar in my state machine ([old version here](https://github.com/IanMercer/AboditStateMachine)). – Ian Mercer Feb 16 '21 at 23:57
  • 1
    I don't see what the state pattern has to do with this. There's nothing different about `friend` in that context from any other context. See duplicate for your options. `internal` and nesting types can be good approaches. C# helps you enforce proper encapsulation across types; in 99.94% of all cases, if you want `friend`, your design needs fixing anyway. – Peter Duniho Feb 17 '21 at 01:42
  • @PeterDuniho The state pattern is relevant because in this specific context it makes a lot of sense for one class to access the internals of other class. You say "In 99.94% of all cases your design needs fixing" and I mostly agree, but in **this** very specific case "friend" or equivalent would be useful and idiomatic in other languages, and I can't think of practical alternatives here. "internal" is overkill because you are effectively making an assembly just for the sake of one class, and nesting types doesn't allow you to reuse the code in the `State` classes. – Ignacio Feb 17 '21 at 03:15
  • _"in this specific context it makes a lot of sense for one class to access the internals of other class"_ -- you obviously believe that. But I've implemented the "state pattern" a number of times, even before anyone was ever calling it that, and have never needed for one object to need to have access to non-public members of another. – Peter Duniho Feb 17 '21 at 03:17
  • @PeterDuniho That sounds good, can you then please provide an answer where you specify how you would do this? Maybe a skeleton of an implementation of the state pattern where it becomes obvious that the internals of the context class don't need to be accessed by `State` classes in any way? This would also answer my question. Instead of "you can use this alternative for friend" the answer would be "When you implement the state pattern you can do such and such else, and in that way you will not need to access the internals of your Context". – Ignacio Feb 17 '21 at 03:24
  • I'm not posting an answer. The question's been closed. You can find an example of the state pattern that doesn't involve `"friend" access on the [Wikipedia page for "State Pattern"](https://en.wikipedia.org/wiki/State_pattern#Java) – Peter Duniho Feb 17 '21 at 03:26
  • @PeterDuniho The wikipedia page has a trivial implementation where the class does essentially nothing, but in any real life scenario this would not be possible. I feel like your attitude towards this question (and towards me) is undeservedly aggressive. I'm not trying to criticise C# or start some sort of fruitless discussion regarding wheather friend is useful or not, I just found myself in a situation where the alternatives I know about are unsuitable or inferior, and I'm looking for a solution. The answer that was marked as duplicate most definitely doesn't solve this issue. – Ignacio Feb 17 '21 at 03:34
  • Your question asks what you can write in C# that would accomplish the same thing as `friend`. That's what the duplicate answers. The point of the Wikipedia page is simply to rebut your claim that the use of `friend` is somehow _inherent_ in the state pattern and address your request for an example that doesn't use it. – Peter Duniho Feb 17 '21 at 03:36
  • As far as your specific issue goes, you should look into "inversion of control". That seems like the most natural way to address what you claim (falsely) can be solved only via a "friend" equivalent. – Peter Duniho Feb 17 '21 at 03:38

0 Answers0