Guard Object in C #

In C ++, it's pretty easy to write a Guard class that takes a reference to a variable (usually a bool), and when the instance object goes out of scope and collapses, the destructor resets the variable to its original value.

void someFunction() {

  if(!reentryGuard) {
    BoolGuard(&reentryGuardA, true);
    // do some stuff that might cause reentry of this function
    // this section is both early-exit and exception proof, with regards to restoring
    // the guard variable to its original state
  }
}

I am looking for an elegant way to do this in C # using a deletion template (or maybe some other mechanism?) I think passing a delegate to a call might work, but it seems a bit more error prone than the guard above. Suggestions are welcome!

Sort of:

void someFunction() {

  if(!reentryGuard) {
    using(var guard = new BoolGuard(ref reentryGuard, true)) {
      // do some stuff that might cause reentry of this function
      // this section is both early-exit and exception proof, with regards to restoring
      // the guard variable to its original state
    }
  }
}

With the understanding that the above code will not work.

+4
source share
4 answers

& hellip; by-ref. , , , "" , , , .

:

class Program
{
    class Guardable<T>
    {
        public T Value { get; private set; }

        private sealed class GuardHolder<TGuardable> : IDisposable where TGuardable : Guardable<T>
        {
            private readonly TGuardable _guardable;
            private readonly T _originalValue;

            public GuardHolder(TGuardable guardable)
            {
                _guardable = guardable;
                _originalValue = guardable.Value;
            }

            public void Dispose()
            {
                _guardable.Value = _originalValue;
            }
        }    

        public Guardable(T value)
        {
            Value = value;
        }

        public IDisposable Guard(T newValue)
        {
            GuardHolder<Guardable<T>> guard = new GuardHolder<Guardable<T>>(this);

            Value = newValue;

            return guard;
        }
    }


    static void Main(string[] args)
    {
        Guardable<int> guardable = new Guardable<int>(5);

        using (var guard = guardable.Guard(10))
        {
            Console.WriteLine(guardable.Value);
        }

        Console.WriteLine(guardable.Value);
    }
}
+2

( -) . , :

( : . , , , )


// usage
GuardedOperation TheGuard = new GuardedOperation() // instance variable
public void SomeOperationToGuard()
{
   this.TheGuard.Execute(() => TheCodeToExecuteGuarded);
}


    // implementation
    public class GuardedOperation
    {
        public bool Signalled { get; private set; }


        public bool Execute(Action guardedAction)
        {
            if (this.Signalled)
                return false;

            this.Signalled = true;
            try
            {
                guardedAction();
            }
            finally
            {
                this.Signalled = false;
            }
            return true;
        }
    }

:



public void SomeOperationToGuard(int aParam, SomeType anotherParam)
{
   // you can pass the params to the work method using closure
   this.TheGuard.Execute(() => TheMethodThatDoesTheWork(aParam, anotherParam);
}

private void TheMethodThatDoesTheWork(int aParam, SomeType anotherParam) {}

Execute, Action, Action <T> Action < T1, T2 >

, Execute, Func <T>

+2

IDisposable .

, , Dispose , using.

:

public class BoolGuard : IDisposable 
{
       .... 
       ...      
        public void Dispose()
        { 
            //DISPOSE IMPLEMANTATION
        }
}
0

, - # .NET Framework, Guard MSDN.

This function will probably need to use the operator Usingto work without going around a block Action, which, as you said, can become messy. Please note that you can only call the object Usingagainst and IDisposablewhich will then be deleted - the perfect trigger to reset the value of the object in question.

0
source

All Articles