-
Notifications
You must be signed in to change notification settings - Fork 26
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
IDisposableAnnotations #130
base: master
Are you sure you want to change the base?
Conversation
ValidCode/IWithAnnotations.cs
Outdated
|
||
public interface IWithAnnotations | ||
{ | ||
[return:Dispose] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DisposedByCaller
is longer but perhaps clearer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Would MustDispose
be clearer (while still short)?
/// The containing method owns the instance and is responsible for disposing it. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] | ||
public class DisposesAttribute : Attribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To come up with an alternative for the sake of discussion: [BecomesOwner]
? [TransferOwnership]
?
[Disposes]
sounds like the method itself does the disposing. Is that always the case or might it be saved for the class to dispose later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to make it a verb to be more explicit for the callers. MustBeDisposed
and NotDisposable
?
/// The return value should be disposed by caller. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)] | ||
public class DisposeAttribute : Attribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just spaghetti: [OwnedByCaller]
? [CallerOwns]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having Disposable
somewhere in the name is good.
/// The return value should not be disposed by caller. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)] | ||
public class DontDisposeAttribute : Attribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the contraction. [NotOwnedByCaller]
?
/// The return value should not be disposed by caller. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)] | ||
public class DontDisposeAttribute : Attribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd spell it out. DoNotDispose
😉
/// The return value should not be disposed by caller. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.ReturnValue | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] | ||
public class DonNotDisposeAttribute : Attribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One too many n
there. ;-)
using System; | ||
|
||
/// <summary> | ||
/// The return value should be disposed by caller. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better if we change should
to must
to be consistent with the attribute's name.
Any progress on this? We would love to see this in action. |
I want to check and see if this will be coming soon? This is a blocking issue for me. |
I don't really remember where we left this but we discussed that it would be nasty if we require the attribute dll to be shipped with applications or the attribute package a package dependency for libraries. We also discussed opening an issue about adding the attributes to the framework but I don't remember what happened with that. |
@JohanLarsson : I asked the question on their gitter, but didn't have any official answer. I have never taken time to ask on the repo |
The way I see it if we dont want to ship attributes, this leaves us with two alternatives:
|
JetBrains' annotations package puts This means that analyzers can see the annotations by using syntax even though the attributes are never emitted at compile time (unless you define the symbol If you add such a NuGet package, you can also include a .targets that keeps the attributes assembly from being copied to build output. I wrote a build trimming tool, so I can help with that. |
I finally asked the question there : https://github.com/dotnet/coreclr/issues/24668 |
What is the current blocking issue here? |
Not sure there is anything blocking, did not really like the design and have not had much time. |
Now that the C# nullability attributes have shipped, I wonder if a similar naming convention could be used. |
What would the names be then? |
https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis?view=netcore-3.0 Taking the concept of directing some at inputs (
|
I'd actually like to see something like this added to the framework and understood by Roslyn's and fxcop's dispose analyzers. |
I came across the case once where I wondered if it was mandatory to dispoed, because I think I read a code in asp.net core where it isn't dispoed: The purpose of the IDisposable here is to say "I don't want to be notified anymore". If the registration is meant to live as long as the application, is the Dispose() really mandatory?
There does not seem to be a big progress here : https://github.com/dotnet/corefx/issues/37873 . I've seen they put a milestone on that but... |
It would be great if we could annotate our APIs with ownership information. Besides our own code, it would be nice if we could somehow annotate third party code as well. See for example I agree with the point posted here that we should avoid having to ship a dll in our release builds. However the annotations should be clear as well, I'm not sure how such a thing can be achieved. For completeness we would need a way to annotate public StreamReader(
[TakesOwnershipWhen("leaveOpen", false)] Stream stream,
bool leaveOpen)
{ } |
/// The ownership of instance is transferred and the receiver is responsible for disposing. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] | ||
public class TakesOwnershipAttribute : Attribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://docs.microsoft.com/en-us/visualstudio/code-quality/ca1813: avoid unsealed attributes
After thinking about this, what if the analyzer contained a source generator that would generate the annotation codes that people can use to control the analyzer part of itself? |
Fixes #126