proposal: ref struct should support destructor #1110
Replies: 36 comments 15 replies
-
Not thrilled with having two subtly different ways to do the same type of thing. If people get excited about using this construct where they would have used Dispose for resource cleanup, instead of just checking whether the type is IDisposable I now also have to check if it has a destructor and create an inner scope in which to put the declaration to deterministically clean up before running the next code in the method. |
Beta Was this translation helpful? Give feedback.
-
Destructible Types #121 |
Beta Was this translation helpful? Give feedback.
-
@jnm2 |
Beta Was this translation helpful? Give feedback.
-
@ygc369 Exactly, the class library authors will only provide one way and that means that I'll have to remember to look for both ways every time I use something resource-y. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 |
Beta Was this translation helpful? Give feedback.
-
@ygc369 That only works if I don't care how long the resource is held. Sometimes I need to release it before the end of the method. A trivial example is something holding a file lock. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 |
Beta Was this translation helpful? Give feedback.
-
For those people who always remember to release resources, this feature will slow us down and make it hard to express what's going on when we add an inner scope. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 ref struct A: IDisposeable
{
FileStream file;
public A(string filename)
{
file = new FileStream(filename, FileMode.Open);
}
...... //other member functions
public void Dispose()
{
if(file)
{
file.Close();
file=null;
}
}
~A() //destructor
{
Dispose();
}
}
static void test()
{
A a=new A("D:\test.txt");
......
} //destructor of "a" would be executed here automatically You can still call "Dispose" method, if you want to release resources earlier. But once you forget, the destructor would help you. Does this satisfy you? |
Beta Was this translation helpful? Give feedback.
-
Instead of adding the new concept of a destructor when .NET already has both That is, if the This interoperates cleanly with a using clause because of the existing contract that allows |
Beta Was this translation helpful? Give feedback.
-
Does the C# team have the plan to support this? Or does the current ref struct already have the feature? |
Beta Was this translation helpful? Give feedback.
-
@theunrepentantgeek One problem here is that |
Beta Was this translation helpful? Give feedback.
-
@ygc369 It looks like your problem really comes down to CS0575: Only class types can contain destructors, which applies to all structs. As you are finding out, using a |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr |
Beta Was this translation helpful? Give feedback.
-
An issue is static void test()
{
A a = new A("D:\test.txt");
A b = a;
A c = a;
......
} // destructor of "a", "b" and "c" executed here automatically? |
Beta Was this translation helpful? Give feedback.
-
It was never a plan, merely a proposal. |
Beta Was this translation helpful? Give feedback.
-
@stephentoub |
Beta Was this translation helpful? Give feedback.
-
Any progress? |
Beta Was this translation helpful? Give feedback.
-
I tend to think of a desire for stack based dispose as both a misunderstanding of the intent of a ref struct and a sign of misuse of the technology. Think of it more like a reference to a 'something' created (and managed) somewhere else higher in the call stack. For instance, Memory is a disposable struct (lets go of its handle making it invalid - even for other copies of that Memory struct), MemoryManager is a disposable class (actually manages memory lifetime, not just handles to it). If you have an instance of MemoryManager class, you can get a Memory struct to pass around a reference to that region of memory (an array or a GCHandle, which may or may not still be valid), but when you get a Span, it's more like saying there's something higher in the stack managing this reference (making it kind of a 'safe' pointer/contract for access to a certain kind of element). It can only live on the stack, so provided the dispose scope of your Memory is the only place calling methods with the Span it provides and the Manager (if) used to get the Memory isn't asynchronously disposed, your Span should remain valid through any method calls made with it. A ref struct should, IMO, always follow this nature. It should be lightweight and specialized for a specific purpose with no need for cleanup, etc. within some parent scope (which is responsible for cleanup, etc). Polymorphism makes no sense on a ref struct because it's specialized purpose should be known to consumers of it (it already is the specialized interface - you got it from somewhere and that somewhere is where your polymorphism comes in). Additionally, it can only live on the stack - it can't be boxed up for consumption by something looking for a specific interface. |
Beta Was this translation helpful? Give feedback.
-
Now C# 8.0 has supported disposable ref structs (see https://blogs.msdn.microsoft.com/dotnet/2019/01/24/do-more-with-patterns-in-c-8-0/). |
Beta Was this translation helpful? Give feedback.
-
I don't think it will. It has already got using declaration, so I don't think we will have another way to do the same: using var fileStream = File.Open("abc.txt"); |
Beta Was this translation helpful? Give feedback.
-
For me using declaration is almost perfect and adds RAII to C# without really adding RAII. What I'm missing here is at least a warning for not calling the |
Beta Was this translation helpful? Give feedback.
-
I think it would be difficult to implement this proposal before "Non-copyable structs (#859)" |
Beta Was this translation helpful? Give feedback.
-
I found myself many times wanting a very simple ref struct destructor. It would be just a method that is called when the ref struct gets out of the scope. Nothing fancy, but I have use cases for it in my framework (I have never used disposing ref structs because I cannot trust the framework user to remember using the using keyword). This proposal is definitively a +1 for me. |
Beta Was this translation helpful? Give feedback.
-
There are currently so many discussions around this topic (#4808, #3450, #121, #5370 and a few others), wouldn't it make sense to merge this into one? Since it already has been discussed in https://github.com/dotnet/csharplang/blob/3c8559f186d4c5df5d1299b0eaa4e139ae130ab6/meetings/2015/LDM-2015-02-11.md#1-destructible-types it is obviously not completely uncommon and need deeper discussion where the ideas from all findings from ongoing discussions can flow in? |
Beta Was this translation helpful? Give feedback.
-
I think |
Beta Was this translation helpful? Give feedback.
-
I am just here to give my support for this feature. I am creating a library and want to release internally used resource to the pool when |
Beta Was this translation helpful? Give feedback.
-
Anything regarding this topic, this would be so valuable.. |
Beta Was this translation helpful? Give feedback.
-
What about an attribute for |
Beta Was this translation helpful? Give feedback.
-
C# without a syncronous destructor on scope exits is just awful. It prevents C# from entering the realm of machine learning. |
Beta Was this translation helpful? Give feedback.
-
Since ref struct is stack-only, it could have a destructor, which would be executed when the struct goes out of scope. If I write a function library for others, although I provide dispose function, users can still ignore it and forget to release resources. I can't force them to use "using". But if ref struct supports destructor, I can use it to wrap my functions to ensure releasing resources.
For example:
related issue: #231
Add a rule: ref struct with destructor can't assign each other.
Beta Was this translation helpful? Give feedback.
All reactions