Monday, October 28, 2019

C# 8.0: Using Declarations and Pattern-Based Using for Ref Structs

In this post, let's go through another feature that was introduced with C# 8.0 which is using declarations and pattern-based using for ref structs.

We are all familiar with using statements. So basically a using statement is something like this.
using (MyDisposableClass myDisposableClass = new MyDisposableClass())
{
    // some code
}
But to this, your MyDisposableClass needs to implement the interface IDisposable.
public class MyDisposableClass : IDisposable
{
    public void Dispose()
    {
        // some code to cleanup your resources
    }
}
And when the control is leaving enclosing scope, the Dispose method in MyDisposableClass will be called.

So what's wrong with this. There is actually nothing wrong, but using statements needs quite a bit of indenting to the code. If you are using multiple objects that need to be disposed of, the code is going to get a bit messy.
// some code 
using (var fileStream = new FileStream(...))
{
    // some code 
    using (var memoryStream = new MemoryStream())
    {
        // may be some other using statement ...
    }
}
Enter using declarations.
using MyDisposableClass myDisposableClass = new MyDisposableClass();
// some code
So now you can just declare the variable with using, and it will continue to work as it was. And when you have multiple usings,
{
    using var fileStream = new FileStream(...);
    using var memoryStream = new MemoryStream();
    ...
    // dispose of memoryStream
    // dispose of fileStream 
}
So here when the control is leaving the scope, the objects will be disposed in the reverse order in which they are declared.

The other feature is pattern-based using for ref structs. Ref strucs which was introduced with C# 7.2 is a struct declared with the ref modifier and it may not implement any interfaces, so can't implement IDisposable. But still, we can try and do something like this.
{
    using MyRefStruct myRefStruct = new MyRefStruct();
    // some code
}
But in order to that, we need to implement dispose pattern here, that is we have a Dispose method, which is public, parameterless and has a void return type.
public ref struct MyRefStruct
{
    public void Dispose()
    {
        // some code to cleanup your resources
    }
}
So in the using, as the control leaves the enclosing scope, the Dispose method will be called.

Hope this helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment