Replies: 2 comments 8 replies
-
Before interfaces were supported on using System;
var target = new FooRefStruct();
using (target) { };
public ref struct FooRefStruct
{
public void Dispose() => Console.WriteLine("Implicit");
} |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Disclaimer: Originally posted at runtime repo, as I was not sure if it was intended language design, a compiler bug, or a general compatibility-driven decision.
One of C# 13 features announced in What's new in C# 13 is to enable ref structs to implement interfaces. It allows ref structs to implement IDisposable interface, moreover it allows them to implement IDisposable explicitly. Currently, when implemented both implicitly and explicitly, ref structs behave differently to other types, e.g. consider the following example:
Run at Sharplab
That is, ref structs prefer implicit* Dispose implementation, while every other type prefers explicit Dispose implementation, conforming to ECMA-334 spec.
*Colloquially called implicit, in other words - not explicit. For ref structs it means choosing a specific method by matching
public void Dispose()
signature, i.e. duck typing.Is this intended design or a bug? If former, would it be possible to reconsider this? Now, it creates a weird behavior, the only purpose of which is to be a nasty puzzler for a programmer interview. If changed, it would be a breaking change, but a very minor one.
To observe such a breaking change, you'll need to explicitly add an IDisposable implementation to an existing ref struct with implicit Dispose method - which is somewhat of a breaking change in itself. Now, if such a struct is used in a Dispose statement - different overload will be called, so it is a source level breaking change, but it's no different from adding explicit Dispose implementation to any regular disposable type anyway. As far as I understand, this is not a binary breaking change - existing binaries that utilize ref struct Disposal have a direct call to implicit Dispose method on IL level anyway - so they will continue to call implicit implementations.
NB
As far as I understand how consistent the behavior is with
allow ref struct
feature (I don't have NET 9.0 version locally with this feature enabled), in generic code an explicit implementation will be used (even though JIT could've replacedcallvirt IDisposable.Dispose
tocall Dispose
due to per-concrete type reification for structs):Which makes non-generic case even more inconsistent.
Beta Was this translation helpful? Give feedback.
All reactions