-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal - Introduce IDisposable ownership annotations #29631
Comments
Are there any works to do for CLR on this feature? First of all, |
Hi,
I think so, or maybe that belongs to the corefx to provide such things. I see it very similar to the introduction of the non-nullable types : It's something that helps write you better code, and if first applied to .net itself, that would greatly help the adoption of such features.
My proposal is not about rules, but more about helping user to spot usages that are different from the intent. Right now, when you look at a method that returns IDisposable, how do you know if you should dispose the object or not?
Implementing that in an analyser would probably be doable, however to be efficient:
I don't want to force that, I want library authors to be able to express the intent : |
CLR has even less knowledge than analyzer. I guess you want to let CLR "auto-detect" a method's ownership of a disposable. But it's even much more harder than verifying and enforcing. If you want something make people to follow the pattern easily, it falls into language design. |
You might be right, this proposal would probably better fit in csharplang, but it will probably have implications in corefx (where annotations will likely be declared). |
@karelz Please either move as requested or close this issue and advise opening another following https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md. |
I think one use case of this could be side note regarding 'Why in .NET?' section: just dispose of both of the instances, since calling Dispose() multiple times won't cause any problems 😝 using (Stream stream = File.Open())
using (StreamReader reader = new StreamReader(stream))
{
// Some nice codes come here
} |
Stream is likely not the best example of usage because you can pass it into a stream reader and transfer ownership, or specify If I understand what you mean, you're telling me that it doesn't hurt to dispose the item twice? Is that always true, or only on Stream? I'm not sure that is something that is always implemented, and I'm pretty sure that I have in my code objects that are not meant to be disposed twice. Anyway, there are still the case where you get a IDisposable object as a result of a method, and where you must not dispose it because that would otherwise close it for the rest of the code. |
Yes, that is correct. It is advised against throwing anything in Dispose/only making it possible to disposing once to ensure cleanup of unmanaged resources. See Implementing a Dispose method:
So I would expect it to be always implemented in such way. But regardless, I think it's a fair point, hence just a side note. |
Hi, is there anything new here? Any chance to see this coming in .net 5? Has this even been triaged/discussed? |
I'm not sure starting in libraries is the right way to move this issue forward. Seems the roslyn-anlyzers is better to work on a change that adds support to an analyzer and detects attributes by name. Typically these types of annotations don't rely on strong typing in specific assembly but support the attribute definition in any assembly and match by namespace.name to allow folks to use it on older frameworks that can't change the API. The same was true for async, nullable, and others. Work out the kinks, drive consensus, and demonstrate the value. Once that happens we could consider adding such a feature to some of the API in dotnet/runtime. We've done investment in analyzers in net5 not sure if there has been explicit consideration for IDisposable. @stephentoub @bartonjs @jeffhandley may know. |
Since this is the only I agree that this will require a very similar shape to nullability annotations, in that it requires a lot of attributes to be placed throughout the codebase, and we need a very complex set of attributes; like For inputs (including
For outputs:
There might be other states. It's as least as complex as nullability, because of something like internal sealed class ReturnWrapper : IDisposable
{
private IDisposable? _disposable;
internal ReturnWrapper([TakesOwnership] IDisposable disposable)
{
_disposable = disposable;
}
public void Dispose()
{
_disposable?.Dispose();
_disposable = null;
}
[HowDoWeDescribeThisState]
internal void SetSuccess()
{
_disposable = null;
}
}
...
using (FileStream stream = File.Open(...))
using (ReturnWrapper wrapper = new ReturnWrapper(stream))
{
...
wrapper.SetSuccess();
return stream;
} The |
FYI: We already have some IDisposable analyzers for detecting dispose leaks in roslyn-analyzers repo.
Current implementation of these analyzers primarily relies on the following for improved analysis precision:
However, these analyzers still lead to false positives and negatives. These would definitely benefit from attribute based annotations for an improved analysis precision.
Agreed. Tagging @Evangelink who has shown interest in this space and is heavily involved in contributions to roslyn-analyzers repo - would you be interested in working with @bartonjs on the initial attribute design and a prototype in enhancing the existing disposable analyzers and/or adding new disposable analyzers in roslyn-analyzers repo? |
I would love to :) |
Another case that needs to be handled by the attribute is the case of overloads with |
This would be really great to have. Are there any plans to add this functionality? |
Anything new on this? EDIT: Why has this issue been assigned to the "team IoT pod" dashboard? |
It depends the direction we take. If we assume everything gets annotated (marked with attributes) then we could go in the direction of not having a special case. We could also have analyzers trying to recognize a pattern (as it is done with the try-pattern), for example we could assume that a method taking something disposable and having a boolean parameter named |
I would love for this to be added. There is no good way to indicate ownership at the moment and the analyzer is going crazy about it. |
Hi,
I have thought about this for a while, and I finally got time for that, so I'm posting here.
Please tell me if that's not the right place to ask for that.
Rationale
I am an average developper that wants to make sure that I don't forget to call
Dispose()
onIDisposable
. What is great is that there's a roslyn analyzer for that : https://github.com/DotNetAnalyzers/IDisposableAnalyzersHowever, sometimes, that analyzer doesn't know how things work, and a signature like
will trigger a warning, while sometime it's just returning a cached copy which is owned by the class.
There is no way for the analyser to know the semantic of what should be disposed and what should not.
Then came the idea that we could provide some attributes that could help the analyzer.
The problem
How to redistribute that kind of attributes?
Each of those options have drawbacks, and probably more than exposed above. Then we thought about it in a different way :
If we truly want to analyze the behavior of the code, what if we find a more universal way : introduce the annotations directly in .net.
The proposition
Here comes the IDisposable ownership attributes. The first formal definition was made here, and I think that the API shape is understandable.
Let's dig into this :
By defining these attributes, we state that "The owner of the object is responsible to
Dispose()
it".Ownership can be given (i.e. transferred to caller):
It can be taken
We can also say explicitely that the resource is kept:
Why in .NET?
Having a way to express ownership is really nice to know what is happening, and many places in the framework itself could benefit from that.
Take this code for example:
Which one should I dispose?
If
StreamReader
declared this constructor asTakesOwnership
, the question is no more.Another question I often have is : "When using
IServiceCollection.AddSingleton()
, are my objects correctlyDispose()
'd?"Potential uses
What do you think?
The text was updated successfully, but these errors were encountered: