diff --git a/docs/standard/garbage-collection/implementing-dispose.md b/docs/standard/garbage-collection/implementing-dispose.md index 61ddf9fa4b9d5..78f2294f24d62 100644 --- a/docs/standard/garbage-collection/implementing-dispose.md +++ b/docs/standard/garbage-collection/implementing-dispose.md @@ -54,8 +54,8 @@ Method signatures are: Because the `public`, non-virtual (`NotOverridable` in Visual Basic), parameterless `Dispose` method is called when it's no longer needed (by a consumer of the type), its purpose is to free unmanaged resources, perform general cleanup, and to indicate that the finalizer, if one is present, doesn't have to run. Freeing the actual memory associated with a managed object is always the domain of the [garbage collector](index.md). Because of this, it has a standard implementation: -:::code language="csharp" source="../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.disposable/cs/Disposable.cs" id="Dispose"::: -:::code language="vb" source="../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.disposable/vb/Disposable.vb" id="Dispose"::: +:::code language="csharp" source="./snippets/dispose-pattern/csharp/Disposable.cs" id="Dispose"::: +:::code language="vb" source="./snippets/dispose-pattern/vb/Disposable.vb" id="Dispose"::: The `Dispose` method performs all object cleanup, so the garbage collector no longer needs to call the objects' override. Therefore, the call to the method prevents the garbage collector from running the finalizer. If the type has no finalizer, the call to has no effect. The actual cleanup is performed by the `Dispose(bool)` method overload. @@ -63,22 +63,22 @@ The `Dispose` method performs all object cleanup, so the garbage collector no lo In the overload, the `disposing` parameter is a that indicates whether the method call comes from a method (its value is `true`) or from a finalizer (its value is `false`). - :::code language="csharp" source="../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.disposable/cs/Disposable.cs" id="DisposeBool"::: - :::code language="vb" source="../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.disposable/vb/Disposable.vb" id="DisposeBool"::: + :::code language="csharp" source="./snippets/dispose-pattern/csharp/Disposable.cs" id="DisposeBool"::: + :::code language="vb" source="./snippets/dispose-pattern/vb/Disposable.vb" id="DisposeBool"::: > [!IMPORTANT] - > The `disposing` parameter should be `false` when called from a finalizer, and `true` when called from the method. In other words, it is `true` when deterministically called and `false` when non-deterministically called. + > The `disposing` parameter should be `false` when called from a finalizer, and `true` when called from the method. In other words, it is `true` when deterministically called and `false` when nondeterministically called. The body of the method consists of three blocks of code: - A block for conditional return if object is already disposed. -- A block that frees unmanaged resources. This block executes regardless of the value of the `disposing` parameter. - A conditional block that frees managed resources. This block executes if the value of `disposing` is `true`. The managed resources that it frees can include: - **Managed objects that implement .** The conditional block can be used to call their implementation (cascade dispose). If you have used a derived class of to wrap your unmanaged resource, you should call the implementation here. - - **Managed objects that consume large amounts of memory or consume scarce resources.** Assign large managed object references to `null` to make them more likely to be unreachable. This releases them faster than if they were reclaimed nondeterministically. +- A block that frees unmanaged resources. This block executes regardless of the value of the `disposing` parameter. + If the method call comes from a finalizer, only the code that frees unmanaged resources should execute. The implementer is responsible for ensuring that the false path doesn't interact with managed objects that may have been disposed. This is important because the order in which the garbage collector disposes managed objects during finalization is nondeterministic. ## Cascade dispose calls diff --git a/samples/snippets/csharp/VS_Snippets_CLR/conceptual.disposable/cs/Disposable.cs b/docs/standard/garbage-collection/snippets/dispose-pattern/csharp/Disposable.cs similarity index 73% rename from samples/snippets/csharp/VS_Snippets_CLR/conceptual.disposable/cs/Disposable.cs rename to docs/standard/garbage-collection/snippets/dispose-pattern/csharp/Disposable.cs index 73479d3215439..41d78aa60204c 100644 --- a/samples/snippets/csharp/VS_Snippets_CLR/conceptual.disposable/cs/Disposable.cs +++ b/docs/standard/garbage-collection/snippets/dispose-pattern/csharp/Disposable.cs @@ -23,11 +23,12 @@ protected virtual void Dispose(bool disposing) if (disposing) { - // TODO: dispose managed state (managed objects). + // Dispose managed state (managed objects). + // ... } - // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. - // TODO: set large fields to null. + // Free unmanaged resources. + // ... _disposed = true; } diff --git a/docs/standard/garbage-collection/snippets/dispose-pattern/csharp/project.csproj b/docs/standard/garbage-collection/snippets/dispose-pattern/csharp/project.csproj new file mode 100644 index 0000000000000..bf05b58274bcb --- /dev/null +++ b/docs/standard/garbage-collection/snippets/dispose-pattern/csharp/project.csproj @@ -0,0 +1,10 @@ + + + + Library + net9.0 + enable + enable + + + diff --git a/samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.disposable/vb/Disposable.vb b/docs/standard/garbage-collection/snippets/dispose-pattern/vb/Disposable.vb similarity index 71% rename from samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.disposable/vb/Disposable.vb rename to docs/standard/garbage-collection/snippets/dispose-pattern/vb/Disposable.vb index e73a67b47f2fc..5951057ac0180 100644 --- a/samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.disposable/vb/Disposable.vb +++ b/docs/standard/garbage-collection/snippets/dispose-pattern/vb/Disposable.vb @@ -13,16 +13,19 @@ ' Protected Overridable Sub Dispose(disposing As Boolean) - If disposed Then Exit Sub + If disposed Then Exit Sub - ' A block that frees unmanaged resources. - If disposing Then - ' Deterministic call… - ' A conditional block that frees managed resources. - End If - - disposed = True + + ' Free managed resources. + ' ... + + End If + + ' Free unmanaged resources. + ' ... + + disposed = True End Sub ' diff --git a/docs/standard/garbage-collection/snippets/dispose-pattern/vb/project.vbproj b/docs/standard/garbage-collection/snippets/dispose-pattern/vb/project.vbproj new file mode 100644 index 0000000000000..fc3f09ab48254 --- /dev/null +++ b/docs/standard/garbage-collection/snippets/dispose-pattern/vb/project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net9.0 + + +