-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Add new ObjectDisposedException constructor overload #51700
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Those all do different things. Which are you proposing the new overload maps to? And are you proposing that all of the other cases in use today change their output as a result? |
For public sealed class ObjectDisposedException
{
+ public static ObjectDisposedException CreateFor<T>() => return new ObjectDisposedException(nameof(T));
} |
I think the different output today is not intentional as I doubt that many developers know the difference between FullName and ToString(). The new implementation could call
It could be another overload but that one will be that useful. There are much fewer cases which do throw new ObjectDisposedException(typeof(T).{FullName|Name|ToString()) and the nameof cases would be better replaced with |
If needed, we can provide a specialized implementation of this ctor that bypasses most of the reflection stack, bypasses caching, and tries to do the most naïve, least complicated thing possible. |
I would not worry about cost of computing the type name for the purpose of this API. It is the least of the problem for throwing ObjectDisposedException. |
I'm not worried about the performance of the ctor call. I'm more worried about the |
The reflection caches are collectible. If it is just one time occurence, the GC will take care of them. |
namespace System
{
public partial class ObjectDisposedException
{
public ObjectDisposedException(object instance);
public ObjectDisposedException(Type type);
}
} |
In the spirit of #48573, I wonder if this should actually be a Throw(object) / Throw(Type) set of static methods? |
Interesting; I'm not opposed to that. |
Reset to api-ready-for-review since the PR seems to have gone ahead with Steve's suggestion. So we should discuss Steve's suggestion. namespace System
{
public partial class ObjectDisposedException
{
[System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute]
[System.Diagnostics.StackTraceHidden]
public static void Throw(System.Object instance) => throw null;
[System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute]
public static void Throw(System.Type type) => throw null;
}
} Part of the motivation being that Also suggestion, |
Two comments on Jeremy's latest proposal. First, should the instance and type arguments be nullable? If somebody passes in null, I think the behavior should be equivalent to the generalized Second, agree that |
What's the scenario? I see them being used as either public sealed partial class Foo
{
public void SomethingFun()
{
if (_disposed)
ObjectDisposedException.Throw(this);
...
}
} or public abstract partial class Bar
{
public void DoAnAwesomeThing()
{
if (_disposed)
ObjectDisposedException.Throw(typeof(Bar));
}
} I don't see a case where |
Scenario would be something like: if (this._disposed) { ObjectDisposedException.Throw(this._wrappedResource); } Where _wrappedResource could possibly be null after this is disposed. I agree it's a bit contrived, and maybe not worth thinking too hard about, but wanted to raise it as a scenario. |
We discussed the method pattern here, and debated for a bit on whether the parameters should be nullable and we concluded no. Since we're early in the release we have time to learn that was wrong. (And going "more nullable" is not breaking) namespace System
{
public partial class ObjectDisposedException
{
[System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute]
[System.Diagnostics.StackTraceHidden]
public static void Throw(System.Object instance) => throw null;
[System.Diagnostics.StackTraceHidden]
[System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute]
public static void Throw(System.Type type) => throw null;
}
} One notable change from the PR state: We added StackTraceHidden to both methods. |
Of the hundreds of call sites changed in #58684, I think all but maybe 4 were of the form: if (condition)
{
ObjectDisposedException.Throw(...);
} and two of the remaining ones could have been written that way. In addition to or instead of Throw, should we have a ThrowIf? public static void ThrowIf(bool condition, object instance)
{
if (condition)
{
Throw(instance);
}
} such that those hundreds of call sites change from: if (condition)
{
ObjectDisposedException.Throw(...);
} to instead be: ObjectDisposedException.ThrowIf(condition, ...); ? |
Either adding If we want to go with less-is-more then I'd say we should just change it, callers with no condition can call Or we could just do it as in-addition, and make ThrowIf be [StackTraceHidden]
public static void ThrowIf([DoesNotReturnIf(true)] bool condition, Type type)
{
if (condition)
{
Throw(type);
}
} Do you want to bounce it back for review again, @stephentoub ? |
Converting to |
namespace System
{
public partial class ObjectDisposedException
{
public static void ThrowIf([DoesNotReturnIf(true)] bool condition, object instance);
public static void ThrowIf([DoesNotReturnIf(true)] bool condition, Type type);
}
} |
Background and Motivation
There is a very common pattern used to handle disposed object state and it involves throwing
ObjectDisposedException
. It requires extra conversion before constructing the exception. There are about 400 cases of this pattern in runtime which could be unified and simplified and more in .NET libraries.Proposed API
namespace System { public class ObjectDisposedException { + public ObjectDisposedException(object instance); }
Usage Examples
All the examples from above could be replaced with simple construction which would extract the name from the instance.
The text was updated successfully, but these errors were encountered: