-
Notifications
You must be signed in to change notification settings - Fork 4k
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
ref structs should not implement interfaces #20226
Comments
What about |
Ref struct is not convertible to an interface, even if it claims to be implementing one. In particilar that would not satisfy the requirememts of |
Well, we could change the requirements of |
fixed in #20293 |
It is definitely not pointless, it can used with generics without boxing. Why can it not be used as a generic type argument? I have a specific need that is blocked by this, namely for my work with Span.Sort? |
I guess it is because there is currently no way to constrain a generic type parameter to avoid possibly boxing it. Why not consider a constraint for this then? Not sure what would be good but: internal interface ISwapper
{
void Swap(int i, int j);
}
internal ref struct Swapper<T> : ISwapper // ref structs can't inherit interfaces :( Nor be generic type parameter
{
Span<T> _items;
public Swapper(Span<T> items)
{
_items = items;
}
public void Swap(int i, int j)
{
ref T start = ref _items.DangerousGetPinnableReference();
SpanSortHelper.Swap(ref Unsafe.Add(ref start, i),
ref Unsafe.Add(ref start, j));
}
}
public void SomeMethod<TSwapper>(TSwapper swapper)
where TSwapper : ref struct
// Although it should still work for normal structs, just restrict the availability of boxing etc.
// "unboxable" :|
{
// Swapper can then be used to inject zero, one or more extra items...
} |
I second @nietras. This limitation prevents the creation of a lot of very useful building blocks. |
As a motivation consider this building block:
And then using this with some implementation:
With optimizations turned on, this compiles to a loop with This can be done with |
Please reconsider this. @jtheisen gives a great example that can benefit heavily from inlining. My specific use-case involves traversing a BST with a custom comparer that'd have a ref to a few larger structs (do not want to make class for variety of reasons). My only alternative is to copy-paste my tree search function so that I can benefit from inlining and avoid big struct copies (in my case, my tree has numerous comparers which satisfy the BST invariant. I'm passing struct comparers to benefit from inlining... but probably too much details). |
See also dotnet/csharplang#1148 and dotnet/csharplang#1147 |
Sorry for reviving a zombie thread but currently hitting the exact same issue. We deal with unmanaged memory A LOT. And the ability to enclose the memory boundaries inside It is certainly not pointless, the more you use |
hi @redknightlois discussions abotu the language go at dotnet/csharplang. See teh linked threads in the post above yours :) this is the repo for the compiler impl. |
@CyrusNajmabadi Yes, but it would really help a lot if the language implementors could tell them what they need to hear. Using unboxed structs as interfaces through generics is possible in C# (and probably VB) since the days of Silverlight, yet the OP's statement proves this isn't common knowledge, even among the experts. And these things are why .NET is so much better than Java, the static language where everything is boxed except ints and floats. You guys know you need to embrace that advantage, and you did of course, with the introduction of Span&Co - but this right here is an oversight that really needs fixing. And it's likely easy to fix, so maybe the language implementors should do that first and then just have it sanctioned by the language people, right? |
No. We don't purposefully deviate in that manner.
It's the same group of people. We just make language changes over at dotnet/csharplang. Then once that is done, the compiler is updated to support the new language version. |
Considering that ref structs cannot be boxed or passed as a generic type argument, implementing interfaces is pointless.
The text was updated successfully, but these errors were encountered: