Proposal: Allow struct members to return ‘this’. #1997
-
I propose the restriction that struct members cannot return references to ‘this’ be dropped. The analysis done at call sites is sufficient to determine validity if struct instance methods are treated as having implicit ‘ref this’ parameters. Consider the declaration of the method X below, which complains: “struct members cannot return ‘this’ or other instance members by reference.” The concern is that the ‘this’ reference might outlive the lifetime of the struct on the stack.
But the method X is equivalent to:
Which is a valid method declaration. Of course, this declaration doesn’t allow the ‘foo’ reference to outlive its lifetime, because we can’t write things like:
Even though these two ‘X’ methods are equivalent, the prohibition on returning For example, the below is well-defined behavior, but is not allowed by C#:
Just as above, the ‘Current’ property is semantically equivalent to
and because the foreach statement won’t cause the ‘foo’ reference to escape foo’s lifetime, this should be allowed. |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments
-
If this behaviour is crucial to your project and you don't mind some unsafe code you can just point to the first field of your struct like so: public unsafe struct Foo
{
public int X, Y;
public ref Foo Current => ref *(Foo*) Unsafe.AsPointer(ref X);
} And on a second thought, doesn't this do exactly what you want? public static class Extensions
{
public static ref T Current<T>(this ref T value) where T : struct => ref value;
} |
Beta Was this translation helpful? Give feedback.
-
namespace Hypothetical
{
// If this were allowed,
struct Foo
{
int value;
public ref int X() => ref value;
}
// this couldn't be allowd.
class Bar
{
public ref int M()
{
Foo x = new Foo();
return ref x.X();
}
}
}
namespace Actual
{
// C# 7.2 allows this
class Bar
{
public ref int M()
{
Foo x = new Foo();
return ref x.X();
}
}
// because of this usecase.
struct Foo
{
int[] array;
public ref int X() => ref array[0];
}
} |
Beta Was this translation helpful? Give feedback.
-
If you want this behavior just use |
Beta Was this translation helpful? Give feedback.
-
@ufccp, that's a great point, it would restrict cases like that which we probably wouldn't want to do. However, given that the use case is very helpful for writing efficient struct-based enumerators, and because you can write something like Here are two alternatives:
|
Beta Was this translation helpful? Give feedback.
-
(2) would effectively bifurcate the entire |
Beta Was this translation helpful? Give feedback.
-
@OyasumiLad This feature is needed when I want to attach interface to the same struct |
Beta Was this translation helpful? Give feedback.
-
There is a proposal that will allow you to do this. As far as I can tell, the championed issue for that is #1147. The issue raised by @ufcpp is addressed by requiring a special attribute an any |
Beta Was this translation helpful? Give feedback.
There is a proposal that will allow you to do this. As far as I can tell, the championed issue for that is #1147.
The issue raised by @ufcpp is addressed by requiring a special attribute an any
struct
method that returnsthis
byref
and treating such methods differently.