• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 279
  • Last Modified:

How can I store a ref of an object within a class for later use?

Experts,

  I have a class in VC++ 6.0 that I use a lot.  It looks like this:

class CLockFlag
{
public:
      CLockFlag(int& iFlag, int iEnter = TRUE, int iExit = FALSE)
            : m_iFlag(iFlag) // this stores the ref
      {
            m_iExit = iExit;
            m_iFlag = iEnter;
      }
      ~CLockFlag()
      {
            m_iFlag = m_iExit; // this modifies the original arg
      }

protected:
      int& m_iFlag; // note the int& type so that the destructor can modify the iFlag that was passed in...
      int m_iExit;
};

  Is there any way to write this class in C#?  There are two issues here, first the int& (it could have been written as int*, but int& is prettier for the users), and the destructor itself.  I'm going to be experimenting with how reliable the destructors are on my own.  I really need to know how to store a ref to the original param that was passed in...

  I've gotten this far:

      public class LockFlag
      {
            #region Private Members
            int m_iFlag; // how can I store a ref to the original iFlag???
            int m_iExit;
            #endregion

            #region Constructors

            public LockFlag(ref int iFlag, int iEnter, int iExit)
            {
                  m_iFlag = iFlag; // this needs to store a ref to iFlag for later modification
                  m_iExit = iExit;
                  m_iFlag = iEnter;
            }
            ~LockFlag()
            {
                  m_iFlag = m_iExit; // this needs to modify the original arg that was passed into the constructor
            }

            #endregion
      }

  Thanks.

Douglas Holt
douglasholt@cox.net
0
DouglasHolt
Asked:
DouglasHolt
  • 7
  • 4
  • 3
1 Solution
 
AlexFMCommented:
I think it is better to write something else instead of copying of C++ class. One of the reasons is that managed class instance is not destroyed immidiately when it goes out of scope. C++ lock object which unlocks protected data in destructor cannot be reproduced by copying C++ code to C#.
Please describe how CLockFlag is supposed to be used, and possibly we can suggest some way to implement this by .NET way.
0
 
DouglasHoltAuthor Commented:
For instance:

// A C++ Example usage of CLockFlag
void SomeFunction()
{
      CLockFlag cLockFlag(m_bIsProcessing, TRUE, FALSE);

      BOOL bRc = DoSomeProcessing();
      if(!bRc)
      {
            return;
      }

      bRc = DoSomeMoreProcessing();
      if(!bRc)
      {
            return;
      }
}

  Basically, there are at least 3 exit points (5 if these functions can throw exceptions...).  By using CLockFlag, m_bIsProcessing is set to TRUE initially, and reset to FALSE as soon as cLockFlag goes out of scope.

  I've been told that while the first version of C# did not have destructors, VS.NET 2003's version of C# does have destructors now.  I haven't experimented yet to see how reliable they are as to scope and when they are called.  I'm assuming that the destructor is distinct from the Dispose method... (sorry, still learning C#).

Thanks.

0
 
AlexFMCommented:
Take a look at C# lock statement and Monitor class.

Read this article:
http://msdn.microsoft.com/msdnmag/issues/03/01/NET/
Specifically: Synchronizing the Microsoft Way
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
DouglasHoltAuthor Commented:
Interesting, but int's are unboxed types, and therefore do not have a SyncBlock associated.  Either way, this is not what I'm looking for.  BTW, Jeffrey Richter is one of my biggest heros.  He probably won't remember, but I actually got to talk to him once back around 1994 (hey, it was a big deal for me!).
0
 
AlexFMCommented:
I think you should read about thread safety both in C++ and C#. C++ class which you are trying to rewrite in C# is not thread-safe. You need to use critical section to make it thread-safe.
0
 
DouglasHoltAuthor Commented:
I am *not* concerned about thread safety with this class.  It is simply not an issue with the way I use it.

I just want a way to store a pointer to a ref object so that I can modify it later in its lifecycle.  Please go back to the original question.  We've gotten way off track...

I *do* appreciate the feedback though!  Please let me know if I haven't been clear enough.  Thanks again.
0
 
NipNFriar_TuckCommented:
You might try this... Also will probable wnat to use the diapose pattern with the IDisposable interface...

     public class LockFlag : IDisposable
     {
          #region Private Members
          bool isDisposed = false;
          int m_iFlag; // how can I store a ref to the original iFlag???
          int m_iExit;
          #endregion

          #region Constructors

          public LockFlag(ref int iFlag, int iEnter, int iExit)
          {
               m_iFlag = iFlag; // this needs to store a ref to iFlag for later modification
               m_iExit = iExit;
               m_iFlag = iEnter;
          }

          // This is called a finalizer method and while similiar to the C++ destructor it is NOT the same
          // This will only be called when the GC is ready to collect this class...
          ~LockFlag()
          {
               Dispose( false );
          }
          public void Dispose() {
               GC.SuppressFinilize( this );
               Dispose( true);
          }
          protected virtual void Dispose( bool disposing ) {
               lock( this ) {
                   m_iFlag = m_iExit; // this needs to modify the original arg that was passed into the constructor
                   if ( disposing && !isDisposed ) {
                       try {
                           // Clean up an resources here...
                       } finally {
                           // If inherited class call base.Dispose( disposing );
                           isDisposed = true;
                       }
                   }
               }
          }

          #endregion
     }

This way when you call Dispose() you will have the ref var updated and you will not risk a resource leak or conflict with the GC.


HTH...
0
 
DouglasHoltAuthor Commented:
 I just got a tip from another user in a different question about how to deal with the destructor issue.  The answer is to implement IDisposable (like NipNFriar_Tuck mentions), but the key is the create the object inside a using block like so:

using(LockFlag lockFlag = new LockFlag(myFlag, true, false))
{
   // Do some work, when this using block exits, the Dispose method of LockFlag will be called immediately (excellent)
   // This is as close to a C++ destructor as C# can get, and I'm pretty happy with it!
}

  Ok, so I've got that hurdle out of the way.  The remaining hurdle is how to store a pointer to the actual myFlag variable so that I can modify it from within LockFlag.Dispose().  The LockFlag class is just one example of *why* I would want to store a ref to an object for later manipulation.

  So, can it be done?

0
 
DouglasHoltAuthor Commented:
Just an update, here's the latest version of LockFlag whose "destructor" works as needed.  It still needs to store a ref to the original flag being passed in though...

public class LockFlag : IDisposable
{
      bool m_FlagRef; // TODO: this needs to be a ref or pointer to the real object...
      bool m_Exit;

      public LockFlag(ref bool Flag, bool Enter, bool Exit)
      {
            m_FlagRef = Flag; // save the real flag for later manipulation (how can I make this work???)
            m_Exit = Exit; // save the exit value
            m_Flag = Enter; // set iFlag to the enter value (how can I make this work???)
      }

      // Use this class in the scope of a using() block to trigger Dispose on scope exit.
      // NOTE: This is how you would implement a psuedo C++ destructor!
      // I.e. using(LockFlag pLockFlag = new LockFlag(m_iMyFlag)){ ... }
      public void Dispose()
      {
            m_FlagRef = m_Exit; // set the original iFlag to the exit value  (how can I make this work???)
      }
}

0
 
NipNFriar_TuckCommented:
I would still implement the full dispose pattern as when I got into the habit of just implementing the IDisposable interface I run into an issue with resources and memory seeming to be leaking on long running applications...

As to your question I would try

public class LockFlag : IDisposable
{
     object m_FlagRef; // By using the object the reference should be kept intact... and since EVERYTHING inherits from object this will work.
     bool m_Exit;

     public LockFlag(ref bool Flag, bool Enter, bool Exit)
     {
          m_FlagRef = Flag; // from a ref to a ref the ref object is not set.
          m_Exit = Exit; // save the exit value
          m_FlagRef = Enter; // set the ref object to the Enter value, no casting (boxing) is needed here since C# will do this automagically
     }

     // Use this class in the scope of a using() block to trigger Dispose on scope exit.
     // NOTE: This is how you would implement a psuedo C++ destructor!
     // I.e. using(LockFlag pLockFlag = new LockFlag(m_iMyFlag)){ ... }
     public void Dispose()
     {
          m_FlagRef = m_Exit; // set the ref object to the Exit value, no casting (boxing) is needed here since C# will do this automagically
     }
}
0
 
DouglasHoltAuthor Commented:
As far as the full dispose pattern, I guess I need to look at that closer.  I don't understand the point of this:

~LockFlag()
{
   Dispose( false );
}

  It looks to me like calling Dispose(false) has no effect...


  As far as the bigger question (saving a ref), I think we're getting closer.  It compiles, but it doesn't work to assign the values to the ref Flag argument.  How can I tell it to assign the ref, not its value?

0
 
NipNFriar_TuckCommented:
What you have to remember is that you are dealing with managed code... Consequently, there are two possible times that the Dispose is called... Once when you call it and once by the GC.  In the case of the GC calling the dispose on the object you do not want to clean up any of the resources as the GC takes care of that and you do not want the GC to try to clean up a resource that has already been cleaned up... On the other hand if you call the dispose you want to make sure all resources are cleaned up and you want to suppress the GC from "finalizing" you object...

As to the bigger question... by casting to an object you will be "boxing" a value and there by passing the reference... i.e.

refFlag = (object) m_Exit;  

should work...
0
 
NipNFriar_TuckCommented:
As an addendum to the last post... there are some DotNET objects that you will always want to dispose such as data connections, since if you do not dispose of them they do not go away cleanly and can take a long time to release the resources.  A close on these objects often does a dispose also...
0
 
DouglasHoltAuthor Commented:
I finally just gave up on trying to store a ref to a primitive value type.  Here's the solution that I came up with, and it works just fine.  Yes, I'm still a proponent of Hungarian notation, for now and always...  Feel free to use it...

using System;

namespace DaVaultSoftwareDesign.Common
{
      /// <summary>
      /// Summary description for LockFlag.
      /// </summary>
      /// <remarks>
      /// <b>Created By: </b>Douglas Holt<br />
      /// <b>Created Date: </b>7 December 2004<br />
      /// <b>Purpose:</b><br/>
      /// Detailed description for LockFlag.
      /// <br/><b>Usage:</b><br/>
      /// <br/><b>Notes:</b><br/>
      /// </remarks>
      public class LockFlag : IDisposable
      {
            #region Private Members

            /// <summary>
            /// A ref of the real object...
            /// </summary>
            Flag m_pFlag;

            /// <summary>
            /// The value to set m_pFlag upon exit of the using block.
            /// </summary>
            Flag m_pExit;

            #endregion

            #region Constructors

            public LockFlag(ref Flag pFlag)
            {
                  m_pFlag = pFlag;
                  m_pExit = new Flag(false);
                  m_pFlag.Bool = true;
            }
            public LockFlag(ref Flag pFlag, bool bEnter)
            {
                  m_pFlag = pFlag;
                  m_pExit = new Flag(false);
                  m_pFlag.Bool = bEnter;
            }
            public LockFlag(ref Flag pFlag, bool bEnter, bool bExit)
            {
                  m_pFlag = pFlag;
                  m_pExit = new Flag(bExit);
                  m_pFlag.Bool = bEnter;
            }
            public LockFlag(ref Flag pFlag, int iEnter)
            {
                  m_pFlag = pFlag;
                  m_pExit = new Flag(0);
                  m_pFlag.Int = iEnter;
            }
            public LockFlag(ref Flag pFlag, int iEnter, int iExit)
            {
                  m_pFlag = pFlag;
                  m_pExit = new Flag(iExit);
                  m_pFlag.Int = iEnter;
            }
            public LockFlag(ref Flag pFlag, Flag pEnter)
            {
                  m_pFlag = pFlag;
                  m_pExit = new Flag(false);
                  m_pFlag.Copy(pEnter);
            }
            public LockFlag(ref Flag pFlag, Flag pEnter, Flag pExit)
            {
                  m_pFlag = pFlag;
                  m_pExit = pExit;
                  m_pFlag.Copy(pEnter);
            }

            #endregion

            #region IDisposable Members

            /// <summary>
            /// Use this class in the scope of a using() block to trigger Dispose on scope exit.
            /// NOTE: This is how you would implement a psuedo C++ destructor!
            /// I.e. using(LockFlag pLockFlag = new LockFlag(m_iMyFlag)){ ... }
            /// </summary>
            public void Dispose()
            {
                  m_pFlag.Copy(m_pExit);
            }

            #endregion
      }


      /// <summary>
      /// A simple flag object for use with LockFlag.
      /// </summary>
      public class Flag
      {
            private bool m_bFlag = false;
            private int m_iFlag = 0;

            public Flag()
            {
                  m_bFlag = false;
                  m_iFlag = 0;
            }
            public Flag(bool bFlag)
            {
                  Bool = bFlag;
            }
            public Flag(int iFlag)
            {
                  Int = iFlag;
            }

            /// <summary>
            /// The Bool representation of this Flag.
            /// </summary>
            public bool Bool
            {
                  get{ return(m_bFlag); }
                  set
                  {
                        m_bFlag = value;
                        m_iFlag = m_bFlag ? 1 : 0;
                  }
            }

            /// <summary>
            /// The Integer representation of this Flag.
            /// </summary>
            public int Int
            {
                  get{ return(m_iFlag); }
                  set
                  {
                        m_iFlag = value;
                        m_bFlag = (m_iFlag != 0);
                  }
            }

            /// <summary>
            /// Copies pFlag's members to this without making an object assignment.
            /// </summary>
            /// <param name="pFlag"></param>
            public void Copy(Flag pFlag)
            {
                  // copy the raw members, don't use the Properties.
                  m_bFlag = pFlag.m_bFlag;
                  m_iFlag = pFlag.m_iFlag;
            }
      }
}
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 7
  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now