Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有办法避免方法调用重复?_C#_.net - Fatal编程技术网

C# 有没有办法避免方法调用重复?

C# 有没有办法避免方法调用重复?,c#,.net,C#,.net,我正在构建一个游戏,其中几个方法相互链接,需要在幕后调用。例如,当一名士兵需要离开城堡时,他一离开城堡,大门就需要打开然后关闭: public void MoveTheGate(bool openTheGate) { if (openTheGate) { // code for: open the gate } else { // code for: close the gate } } public void

我正在构建一个游戏,其中几个方法相互链接,需要在幕后调用。例如,当一名士兵需要离开城堡时,他一离开城堡,大门就需要打开然后关闭:

public void MoveTheGate(bool openTheGate)
{
    if (openTheGate)
    {
        //  code for: open the gate
    }
    else
    {
        //  code for: close the gate
    }
}

public void GetOutOfTheCastle()
{
    MoveTheGate(true);

    //  code for: get out of the castle

    MoveTheGate(false);
}
同样,当来自另一个王国的信使到达城堡时,必须在信使进入城堡的开始和结束时调用
MoveTheGate()
方法

有没有更微妙的方法来实现这一点?

你可以这样做

OpenGate(()=>
  { stuff to do with gate open }
);
OpenGate在哪里

public void OpenGate(Action action)
{
    try
    {
      MoveTheGate(true);
      action();
   }
   finally 
   {
    MoveTheGate(false);
   }
}

这可能完全是过火了,但您可以始终实现
IDisposable
,然后使用
块使用
。这是“确保”它发生的好方法

如果您设置了一个类来调用dispose上的某个给定操作

public class DelegateDisposable : IDisposable
{
    private readonly Action action;

    public DelegateDisposable(Action action)
    {
        this.action = action;
    }

    public void Dispose()
    {
        if(this.action != null)
        {
            this.action();
        }
    }
}
然后你可以这样使用它:

private IDisposable OpenGate()
{
    MoveTheGate(true);
    return new DelegateDisposable(() => MoveTheGate(false));
}
public void GetOutOfTheCastle()
{
    using (OpenGate())
    {
        //  code for: get out of the castle
    }
}
然后像这样使用它:

private IDisposable OpenGate()
{
    MoveTheGate(true);
    return new DelegateDisposable(() => MoveTheGate(false));
}
public void GetOutOfTheCastle()
{
    using (OpenGate())
    {
        //  code for: get out of the castle
    }
}

这种方法的一个很好的优点是它不会弄乱您的调用堆栈,尽管它确实有一些开销。但是,如果您将
DelegateDisposable
引入某个实用程序类,它可能也会对其他应用程序有用。

我会不偏不倚地对待一种继承模式,该模式会强制您在继承的基本抽象类的上下文中执行操作。我认为这更可取的原因是,它允许您轻松地封装门的打开和关闭,并且不会暴露发生这种情况的条件或继承场景之外的功能

public void Main()
{
    var x = new InheritedAction();
}

public abstract class BaseGateAction
{
    public void PerformBaseAction(Action actionToPerformWhileGateIsOpen)
    {
        Open();
        actionToPerformWhileGateIsOpen();
        Close();
    }

    private void Open()
    {
        Console.WriteLine("Gate has been opened");
    }

    private void Close()
    {
        Console.WriteLine("Gate has been closed");
    }
}

public class InheritedAction : BaseGateAction
{
    public InheritedAction()
    {
        PerformBaseAction(() => 
            Console.WriteLine("Attack the dragon while the gate is open"));

        PerformBaseAction(() => 
        {
            Console.WriteLine("Attack the dragon while the gate is open");
            Console.WriteLine("The dragon is victorious and you have been devoured");
        });
    }
}
此代码示例分别为两个PerformBaseAction方法调用输出以下内容:

Gate has been opened
Attack the dragon while the gate is open
Gate has been closed

Gate has been opened
Attack the dragon while the gate is open
The dragon is victorious and you have been devoured
Gate has been closed
这将不仅允许更好的代码重用,而且允许更多的封装逻辑。您始终可以添加附加的公开方法,这些方法采用的前置条件或后置条件将影响您是否可以打开大门

public abstract class BaseGateAction
{
    ....    
    public void PerformBaseActionWithPrecondition(Func<bool> precondition, Action actionToPerformWhileGateIsOpen)
    {
        if (precondition())
        {
            PerformBaseAction(actionToPerformWhileGateIsOpen);
        }
        else
        {
            Console.WriteLine("The gate could not be opened!");
        }
    }
    ...
}

工作代码与StackOverflow无关。你可能想看看,这完全取决于注释掉的代码是什么。如果有一种方法可以重用很多,那么一定要保留单一的方法。按照@Pierre LucPineault的建议,在代码评审中发布完整的代码。不过,请注意,代码评审不允许使用存根代码。您必须发布整个方法。您好@Pierre Luccineault,谢谢您的建议,我不希望我的代码被审查,我正在寻找更优雅的方法来处理由于不得不不断重复这些方法而导致的代码中的丑陋。上面的代码只是一个例子。但也要记住,方法是为了重用而设计的。这样您的代码很好(尽管我肯定会将bool方法分为两个方法),其他选项可能会降低可读性或引入过度设计。在很大程度上也取决于您当前的体系结构,您可能可以通过简单的继承来隐藏所有重复的行为。虽然这确实可行,但在不需要清理非托管资源的情况下实现IDisposable会让人感觉不舒服。@DavidL这是对调用堆栈所做的操作与代码清理程度之间的折衷,还有你的原则。我已经看过——虽然我想不出在哪里——一些我很尊重的项目,它们使用了
IDisposable
来处理类似的事情,我并不介意。我认为“大门”是一种需要清理的资源,尽管我完全明白你的观点——它与开放式溪流或其他东西并不完全相同。