代码之家  ›  专栏  ›  技术社区  ›  Quimby

我应该假设每个拥有的实例都实现IDisposable吗?

  •  0
  • Quimby  · 技术社区  · 6 年前

    我正在研究我的小游戏项目,作为学习和实践C的一种方式,我遇到了一个设计问题。假设我们有以下一组类:

    interface IGameState
    {
        //Updates the state and returns next active state
        //(Probably itself or a new one)
        IGameState Tick();
    }
    class Game
    {
        public Game(IGameState initialState)
        {
            activeState = initialState;
        }
        public void Tick()
        {
            activeState = activeState.Tick();
        }
        IGameState activeState;
    }
    

    游戏基本上是游戏状态的状态机。我们可以 MainMenuState , LoadingState SinglePlayingState 。但是添加 MultiplayerState (表示玩多人游戏)需要一个插座连接到服务器:

    class MultiplayerState : IGameState, IDisposable
    {
        public IGameState Tick()
        {
            //Game logic...
            //Communicate with the server using the Socket
            //Game logic...
            //Render the game
            return this;//Or something else if the player quits
        }
    
        public void Dispose()
        {
            server.Dispose();
        }
        //Long-living, cannot be in method-scope
        Socket server;//Or similar network resource
    }
    

    好吧,这是我的问题,我不能把它传给 Game 因为它不知道应该处理掉它,而调用代码不容易知道游戏何时不再需要它。这个类设计几乎正是我到目前为止实现的,我可以添加 IDisposable IGameState 但我认为它毕竟不是一个好的设计选择 依甲氨基甲酸盐 S拥有资源。此外,该状态机在某种意义上是动态的,任何活动的 依甲氨基甲酸盐 可以返回新状态。所以 游戏 真的不知道哪一个是一次性的,哪一个是一次性的,所以它只需要测试所有的东西。

    所以我问了几个问题:

    • 如果我有一个类声明对非密封类型(例如 initialState 在游戏中)我应该一直假设 可识别 ?(可能没有)
    • 如果我有 可识别 例如,我是否应该放弃它的所有权,将其强制转换为不实现的基础 可识别 ?(可能没有)

    我从中了解到 可识别 感觉像一个非常独特的界面 有损的 (*)语义-它关心自己的生命周期。这似乎与提供有保证但不确定的内存管理的GC本身的思想直接冲突。我来自C++背景,所以它真的感觉到它试图实现RAII概念,但是只要有0个引用,就可以手动调用Debug(析构函数)。我不是说这是对C的咆哮,更像是我缺少了一些语言特性吗?或者可能是特定于C的模式?我知道有 using 但这只是方法范围。下一个是终结器,它可以确保调用Dispose,但仍然是不确定的,还有其他什么吗?也许像C++一样自动引用计数 shared_ptr ?

    正如我所说,上面的例子可以通过不同的设计来解决(但我认为不应该),但不能回答那些可能无法解决的情况,所以请不要太关注它。理想情况下,我希望看到解决类似问题的一般模式。

    (*)对不起,也许不是个好词。但我的意思是很多接口表示一种行为,如果类实现了所说的接口,它只会说“嘿,我可以 做这些事情,但如果你忽视我的那一部分,我仍然工作得很好”。忘记 可识别 不是 无损 . 我发现了 question 这表明,IDisposable可以通过组合传播,也可以通过继承传播。这对我来说似乎是正确的,需要更多的打字,但是好的。这就是 多层状态 感染了。但在我的例子中 游戏 它还想向上游扩散,这感觉不太对劲。

    最后一个问题可能是是否应该有 有损的 接口,比如它是否是工作的正确工具,在这种情况下是什么?或者有其他常用的 有损的 我知道的界面应该是什么?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Michael Puckett II    6 年前

    IDisposable

    MultiplayerState GameState

     public void Dispose()
     {
          server.Dispose();
          GC.SuppressFinalize(this);
     }
    
     ~MultiplayerState() => Dispose()
    

    here