C
C#2w ago
Faker

✅ Dispose method to "dispose" file resource when using LogTo method

Hello guys, I'm trying to implement some simple logging in my DbContext. I want to write the logs in a file; when done, I need to dispose/close the file. I read that we can't use the using keyword because this would mean that our file stream will be closed and we won't be able to open it again (I thing, can someone please confirm please) and so we need to use the Dispose method.
C#
public override void Dispose()
{
base.Dispose();
_logStream.Dispose();
}
C#
public override void Dispose()
{
base.Dispose();
_logStream.Dispose();
}
Here is what is written in the docs, but I have the warning CA1816. I didn't understand what exactly I need to do, I can just add this line: GC.SuppressFinalize(this); ?
12 Replies
cap5lut
cap5lut2w ago
finalizers are special methods (like the constructor) that might run before the instance is actually destroyed and its memory is "released". they are a last resort fallback to free unmanaged resources, in case the user of the type forgot to call dispose themselves. if dispose is called, all resources should be freed already, so there is no need to run that finalizer. u most likely dont have a finalizer in ur class, but ur class is not sealed, so a derived type could end up having a finalizer. disposing an object means that you are done with it, its bad practice to "revive" such an object and it adds a lot of complexity. the better practice here is to simply dispose, and create a new instance. now to the logging part: logging is a solved problem, use existing solutions like Microsoft.Extensions.Logging and/or serilog for logging. these logging frameworks are fleshed out and have decades of experience and improvements. it works, u have less code to maintain and can worry about ur actual code
cap5lut
cap5lut2w ago
ef core has for example MS.E.Logging integration: https://learn.microsoft.com/en-us/ef/core/logging-events-diagnostics/
Overview of logging and interception - EF Core
Overview of logging, events, interceptors, and diagnostics for EF Core
Faker
FakerOP2w ago
oh, I was working with the simple logging, which uses the LogTo method, it's better to just switch to microsoft.logging ? ahh ok, they only work as a fallback, then ? yeah, my class isn't sealed, just to make sure that if ever there are other classes that inherit from this class, we set up a finalizer for them?
cap5lut
cap5lut2w ago
definitively, almost everything uses MS.E.Logging as logging facade (often combined with serilog as logging backend for structured logging) yes only as last resort fallback, there is no guarantee that finalizers are actually executed. (sorry forgot to mention that) while process memory and opened file handles are automatically returned to the OS/the latter closed on process exit, other unmanaged resources might not. a typical example is GPU memory, if u upload for example a texture to the GPU, it stays there until u free it. if ur process exists without doing so, that memory isnt usable until u restart the system. for such stuff the finalizer exists. "lets pray that we can clean up the mess the user caused"
Faker
FakerOP2w ago
yep I see
cap5lut
cap5lut2w ago
if ever there are other classes that inherit from this class, we set up a finalizer for them?
no, u dont set up a finalizer for them. they might implement a finalizer. the typical dispose pattern for unsealed types is:
public class Example : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// clean up managed resources (if any)
}
// clean up unmanaged resources (if any)
}
}
public class Example : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// clean up managed resources (if any)
}
// clean up unmanaged resources (if any)
}
}
and a derived class with a finalizer would be
public sealed class UnmanagedResourcesExample : Example
{
private IntPtr _unmanagedMemory;
public UnmanagedResourcesExample()
{
_unmanagedMemory = NativeMemory.Alloc(512);
}

protected override Dispose(bool disposing)
{
// doesnt have have managed resources that need disposing so no if (disposing) here
NativeMemory.Free(_unmanagedMemory);
base.Dispose(disposing);
}

~UnmanagedResourcesExample()
{
Dispose(false);
}
}
public sealed class UnmanagedResourcesExample : Example
{
private IntPtr _unmanagedMemory;
public UnmanagedResourcesExample()
{
_unmanagedMemory = NativeMemory.Alloc(512);
}

protected override Dispose(bool disposing)
{
// doesnt have have managed resources that need disposing so no if (disposing) here
NativeMemory.Free(_unmanagedMemory);
base.Dispose(disposing);
}

~UnmanagedResourcesExample()
{
Dispose(false);
}
}
finalizers are a bit tricky. because they run directly before the memory is collected/freed, if u mess up in the finalizer, u could happen to "revive" the instance. an instance is collected when there is no reference to it anymore, so if u eg would add this in a finalizer to some other instance thats still alive and it stores that reference, you rooted it again. then the GC wont collect the instance. but u wasted quite some GC's time because it went through the struggle to determine that it was ready for collection. (and it would also end up in a higher generation)
Faker
FakerOP2w ago
yeah I see, I need to read a bit more about them but I now have an overview, thanks ! Will come back if I have other questions
cap5lut
cap5lut2w ago
Implement a Dispose method - .NET
In this article, learn to implement the Dispose method, which releases unmanaged resources used by your code in .NET.
cap5lut
cap5lut2w ago
thats an article u want to read if u want to gracefully free resources
Faker
FakerOP2w ago
Noted, I will have a look 👍
cap5lut
cap5lut2w ago
if u feel like ur questions are answered, dont forget to mark the thread as that by $close ing it
MODiX
MODiX2w ago
If you have no further questions, please use /close to mark the forum thread as answered

Did you find this page helpful?