- https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1063
- Every unsealed type that declares and implements the IDisposable interface must provide its own protected virtual void Dispose(bool) method. Dispose() should call Dispose(true), and the finalizer should call Dispose(false). If you create an unsealed type that declares and implements the IDisposable interface, you must define Dispose(bool) and call it. For more information, see Clean up unmanaged resources (.NET guide) and Dispose pattern.
private bool swigCMemOwn { get; set; }
private bool isDisposeQueued = false;
+ private bool disposedThis = false;
+
/// <summary>
/// Create an instance of Disposable.
/// </summary>
/// Dispose.
/// </summary>
/// <since_tizen> 6 </since_tizen>
- ~Disposable()
- {
- if (!isDisposeQueued)
- {
- isDisposeQueued = true;
- DisposeQueue.Instance.Add(this);
- }
- }
+ ~Disposable() => Dispose(false);
/// <summary>
/// Dispose.
/// <since_tizen> 6 </since_tizen>
public void Dispose()
{
- //Throw excpetion if Dispose() is called in separate thread.
- if (!Window.IsInstalled())
+ Dispose(true);
+ System.GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Hidden API (Inhouse API).
+ /// Dispose.
+ /// </summary>
+ /// <remarks>
+ /// Following the guide of https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose.
+ /// This will replace "protected virtual void Dispose(DisposeTypes type)" which is exactly same in functionality.
+ /// </remarks>
+ /// <param name="disposing">true in order to free managed objects</param>
+ // Protected implementation of Dispose pattern.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposedThis)
{
- Tizen.Log.Error("NUI", "This API called from separate thread. This API must be called from MainThread.");
return;
}
- if (isDisposeQueued)
+ if (disposing)
{
- Dispose(DisposeTypes.Implicit);
+ // TODO: dispose managed state (managed objects).
+ // Explicit call. user calls Dispose()
+
+ //Throw excpetion if Dispose() is called in separate thread.
+ if (!Window.IsInstalled())
+ {
+ throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread.");
+ }
+
+ if (isDisposeQueued)
+ {
+ Dispose(DisposeTypes.Implicit);
+ }
+ else
+ {
+ Dispose(DisposeTypes.Explicit);
+ }
}
else
{
- Dispose(DisposeTypes.Explicit);
- System.GC.SuppressFinalize(this);
+ // Implicit call. user doesn't call Dispose(), so this object is added into DisposeQueue to be disposed automatically.
+ if (!isDisposeQueued)
+ {
+ isDisposeQueued = true;
+ DisposeQueue.Instance.Add(this);
+ }
}
+
+ // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
+ // TODO: set large fields to null.
+
+ disposedThis = true;
}
/// <summary>
//A Flag to check who called Dispose(). (By User or DisposeQueue)
private bool isDisposeQueued = false;
+ private bool disposedThis = false;
+
/// <summary>
/// Create an instance of BaseHandle.
/// </summary>
/// Dispose.
/// </summary>
/// <since_tizen> 3 </since_tizen>
- ~BaseHandle()
- {
- if (!isDisposeQueued)
- {
- isDisposeQueued = true;
- DisposeQueue.Instance.Add(this);
- }
- }
+ ~BaseHandle() => Dispose(false);
/// <summary>
/// Event when a property is set.
/// <since_tizen> 3 </since_tizen>
public void Dispose()
{
- //Throw excpetion if Dispose() is called in separate thread.
- if (!Window.IsInstalled())
+ Dispose(true);
+ System.GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Hidden API (Inhouse API).
+ /// Dispose.
+ /// </summary>
+ /// <remarks>
+ /// Following the guide of https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose.
+ /// This will replace "protected virtual void Dispose(DisposeTypes type)" which is exactly same in functionality.
+ /// </remarks>
+ /// <param name="disposing">true in order to free managed objects</param>
+ // Protected implementation of Dispose pattern.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposedThis)
{
- Tizen.Log.Error("NUI", "This API called from separate thread.This API must be called from MainThread.");
return;
}
- if (isDisposeQueued)
+ if (disposing)
{
- Dispose(DisposeTypes.Implicit);
+ // TODO: dispose managed state (managed objects).
+ // Explicit call. user calls Dispose()
+
+ //Throw excpetion if Dispose() is called in separate thread.
+ if (!Window.IsInstalled())
+ {
+ throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread.");
+ }
+
+ if (isDisposeQueued)
+ {
+ Dispose(DisposeTypes.Implicit);
+ }
+ else
+ {
+ Dispose(DisposeTypes.Explicit);
+ }
}
else
{
- Dispose(DisposeTypes.Explicit);
- System.GC.SuppressFinalize(this);
+ // Implicit call. user doesn't call Dispose(), so this object is added into DisposeQueue to be disposed automatically.
+ if (!isDisposeQueued)
+ {
+ isDisposeQueued = true;
+ DisposeQueue.Instance.Add(this);
+ }
}
+
+ // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
+ // TODO: set large fields to null.
+
+ disposedThis = true;
}
+
/// <summary>
/// Performs an action on this object with the given action name and attributes.
/// </summary>
private bool swigCMemOwn;
private bool disposed;
private bool isDisposeQueued = false;
+ private bool disposedThis = false;
private MeasureSpecification parentMeasureSpecificationWidth;
private MeasureSpecification parentMeasureSpecificationHeight;
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
}
+ /// <summary>
+ /// Hidden API (Inhouse API).
+ /// Destructor.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ ~FlexLayout() => Dispose(false);
+
/// <inheritdoc/>
/// <since_tizen> 6 </since_tizen>
public void Dispose()
{
- // Throw exception if Dispose() is called in separate thread.
- if (!Window.IsInstalled())
+ Dispose(true);
+ System.GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Hidden API (Inhouse API).
+ /// Dispose.
+ /// </summary>
+ /// <remarks>
+ /// Following the guide of https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose.
+ /// This will replace "protected virtual void Dispose(DisposeTypes type)" which is exactly same in functionality.
+ /// </remarks>
+ /// <param name="disposing">true in order to free managed objects</param>
+ // Protected implementation of Dispose pattern.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposedThis)
{
- Tizen.Log.Error("NUI", "This API called from separate thread.This API must be called from MainThread.");
return;
}
- if (isDisposeQueued)
+ if (disposing)
{
- Dispose(DisposeTypes.Implicit);
+ // TODO: dispose managed state (managed objects).
+ // Explicit call. user calls Dispose()
+
+ //Throw excpetion if Dispose() is called in separate thread.
+ if (!Window.IsInstalled())
+ {
+ throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread.");
+ }
+
+ if (isDisposeQueued)
+ {
+ Dispose(DisposeTypes.Implicit);
+ }
+ else
+ {
+ Dispose(DisposeTypes.Explicit);
+ }
}
else
{
- Dispose(DisposeTypes.Explicit);
- System.GC.SuppressFinalize(this);
+ // Implicit call. user doesn't call Dispose(), so this object is added into DisposeQueue to be disposed automatically.
+ if (!isDisposeQueued)
+ {
+ isDisposeQueued = true;
+ DisposeQueue.Instance.Add(this);
+ }
}
+
+ // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
+ // TODO: set large fields to null.
+
+ disposedThis = true;
}
/// <inheritdoc/>
if (type == DisposeTypes.Explicit)
{
- // Called by User
- // Release your own managed resources here.
- // You should release all of your own disposable objects here.
-
+ //Called by User
+ //Release your own managed resources here.
+ //You should release all of your own disposable objects here.
}
- // Release your own unmanaged resources here.
- // You should not access any managed member here except static instance.
- // because the execution order of Finalizes is non-deterministic.
+ //Release your own unmanaged resources here.
+ //You should not access any managed member here except static instance.
+ //because the execution order of Finalizes is non-deterministic.
if (swigCPtr.Handle != global::System.IntPtr.Zero)
{
if (swigCMemOwn)
{
swigCMemOwn = false;
- Interop.FlexLayout.DeleteFlexLayout(swigCPtr);
+ ReleaseSwigCPtr(swigCPtr);
}
swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
+
disposed = true;
}
/// <summary>
+ /// Hidden API (Inhouse API).
+ /// Release swigCPtr.
+ /// </summary>
+ /// This will not be public opened.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
+ {
+ Interop.FlexLayout.DeleteFlexLayout(swigCPtr);
+ }
+
+ /// <summary>
/// Creates a FlexLayout object.
/// </summary>
/// <since_tizen> 6 </since_tizen>
this.frameBroker.SendLaunchRequest(appControl, true);
}
+ /// <summary>
+ /// Hidden API (Inhouse API).
+ /// Dispose.
+ /// </summary>
+ /// <param name="disposing"></param>
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void Dispose(bool disposing)
{
public void Dispose()
{
Dispose(true);
+ System.GC.SuppressFinalize(this);
}
}
}