保证在C#中的同一作用域中的另一个函数之后调用该函数

时间:2018-03-16 16:20:02

标签: c#

我的问题主要是关于C#中的代码安全案例。

以下是代码:

void foo() {
 theFirst();
 //some code which needs to call theFirst() before executing goes here
 definitelyShouldBeCalledAfterTheFirst();
}

现在我想确保在调用函数theFirst()的每个范围(基本上是任何方法)中,函数definitelyShouldBeCalledAfterTheFirst()之后在同一范围内调用。在theFirst()definitelyShouldBeCalledAfterTheFirst()来电之间我需要在大多数时间调用其他函数,我无法在definitelyShouldBeCalledAfterTheFirst()之后或theFirst()之前调用函数。

4 个答案:

答案 0 :(得分:3)

也许这样的代表可以提供帮助:

void ExecuteBetweenFirstAndSecond(Action action)
{
    bool success = false;

    try
    {
       First();
       success = true;
       action?.Invoke();
    }
    finally
    {
       //Uncomment if you want to execute Second only if First wast executed successfully
       //if (success)     
       Second();
    }                   
}

答案 1 :(得分:1)

根据具体情况,有多种方法可以实现这一目标。

@SENya给出great option using delegates

另一种方法是拥有共享基类(尽管此选项仅适用于一小部分方案)。

abstract class MyBaseClass
{
    void doFirst() =>
        Debug.WriteLine("Done First");
    void definitelyShouldBeCalledAfterTheFirst() =>
        Debug.WriteLine("Done After First");    
    protected virtual void doSomething() => 
        Debug.WriteLine("between first and after first");
    public void DoStuff()
    {
        doFirst();
        doSomething();
        definitelyShouldBeCalledAfterTheFirst();
    }
}

class MyClass: MyBaseClass {}
class MyOtherClass: MyBaseClass 
{
    protected override void doSomething() =>
        Debug.WriteLine("something else happens now");
}

void Main()
{
    var a = new MyClass();
    a.DoStuff();
    /* outputs:
        Done First
        between first and after first
        Done After First
    */
    var b = new MyOtherClass();
    b.DoStuff();
    /* outputs:
        Done First
        something else happens now
        Done After First
    */
}

答案 2 :(得分:1)

如果我理解你的问题你有以下要求:

  1. 有一个始终执行第一个的功能,
  2. 有一个始终执行最后一个的功能,
  3. 可以按任何顺序执行但不能先执行或最后执行的其他一些功能。
  4. 什么功能总是执行并执行第一个?构造函数...... 因此,如果您创建一个类并在构造函数中调用First()函数,则满足要求#1。

    确保执行顺序符合要求#3很容易。在构造函数之前不会执行任何代码。如果你设置了一个已经执行了Last()函数的标志,你可以在每个函数的开头检查该标志,如果已经设置则抛出/返回。

    最难的部分是确保执行Last()功能。最接近的保证是实施IDisposable,但您无法保证在using内调用您的课程。

    所以我们最终得到的结论是:

    public sealed class Foo: IDisposable
    {
        private bool isLastCalled = false;
    
        public Foo()
        {
            First();
        }
    
    
        public void First()
        {
            if (isLastCalled) return;
    
            // do something...
        }
        public void Other()
        {
            if (isLastCalled) return;
    
            // do something...
        }
    
        public void Last()
        {
            if (isLastCalled) return;
    
            isLastCalled = true;
    
        }
    
        public void Dispose()
        {
            Last();
        }
    
        ~Foo()
        {
            Last();
        }
    }
    

    附加说明:

    • First()将从构造函数自动调用,但您可以在调用Last()之前再次调用它。如果这不是你的意图 - 制作函数private并删除检查标志

    • 您可以显式调用Last(),也可以在实例超出范围时自动调用它。如果您不需要明确调用它,请将其private

答案 3 :(得分:0)

这就是try-finally的用途。非常简单。如果对theFirst的调用成功,那么即使“某些代码”失败,也可以保证对sureShouldBeCalledAfterTheFirst的调用。

void foo()
{
    theFirst();
    try
    {
        // some code
    }
    finally
    {
        definitelyShouldBeCalledAfterTheFirst();
    }
}