Replies: 14 comments 3 replies
-
I apologize if I'm missing the obvious! Why not make it a |
Beta Was this translation helpful? Give feedback.
-
I really like this idea, and having the ability to quickly declare a @jnm2 Having a third, optional |
Beta Was this translation helpful? Give feedback.
-
Exactly, you would have to add a new property if you didn't want to change the API of your code (and practically impossible with indexers), and |
Beta Was this translation helpful? Give feedback.
-
So the concern here is binary compatibility? For implementing an interface you could use explicit implementation: public interface IFoo
{
object Bar { get; }
}
public class Foo : IFoo {
public ref object Bar => ref bar;
object bar;
object IFoo.Bar => Bar;
} |
Beta Was this translation helpful? Give feedback.
-
@yaakov-h Binary compatibility is not the only concern, but also the possibility of shorter and (in my opinion) cleaner code. To be honest, ref properties have a bit different feeling semantically to me than ref accessors. Ref properties (which also impair the possibility of reasonable reflection on them) feel like a C++ approach to the problem, instead of using the full potential of properties. Also explicit implementation is possible, but a bit wordy for something as simple as a property. Using the proposal: public class Foo : IFoo {
public object Bar { get; set; ref; } //no more code needed
} No need to create a backing field, no need for explicit implementation. Just good old property but buffed up. Compare: interface IIndexable<TIndex, TElement>
{
TElement this[TIndex index] { get; set; }
}
interface IRefIndexable<TIndex, TElement> : IIndexable<TIndex, TElement>
{
new ref TElement this[TIndex index] { get; }
}
class MyClass : IRefIndexable<int, object>
{
object[] arr;
public ref object this[int index] => ref arr[index];
object IIndexable<int, object>.this[int index]
{
get => this[index];
set => this[index] = value;
}
} with: interface IIndexable<TIndex, TElement>
{
TElement this[TIndex index] { get; set; }
}
interface IRefIndexable<TIndex, TElement> : IIndexable<TIndex, TElement>
{
TElement this[TIndex index] { ref; }
}
class MyClass : IRefIndexable<int, object>
{
object[] arr;
public object this[int index]
{
get; set; ref => arr[index];
}
} So the reasons are: unification, binary compatibility, semantics, and shorter code. |
Beta Was this translation helpful? Give feedback.
-
I'd also be nice to be able to do the same for public int Property{get; ref readonly; } That would be translated into something like: int field;
public int get_Property() => field;
public ref readonly int ref_Property() => ref field; Also, this proposal would be handy with classes that expose [JsonProperty(nameof(Property))]
private int SerializableProperty => somefield;
public ref Property => ref somefield; But with this new proposal, it should be possible to do just this: [JsonProperty(nameof(Property))]
public int Property
{
private get => somefield; // For serialization only
public ref => ref somefield;
} Which looks a bit cleaner 👍 |
Beta Was this translation helpful? Give feedback.
-
@Sergio0694 Yeah, I was thinking about this possibility with the At the moment, the development of C# kinda gets ahead of CLR, with by-ref reflection not implemented at all, and by-ref-like types still not supported as returns. |
Beta Was this translation helpful? Give feedback.
-
I am firmly in the camp of those extremely eager to see the ability to pass a property by |
Beta Was this translation helpful? Give feedback.
-
It is not the only way, but the other one is creating a temporary variable which is then assigned to the property after the method call, like what VB.NET does. The problem with that is that storing the reference into a variable is complicated, because accessing the property must be consistent with the reference in all places. You cannot obtain a reference to a property if you don't own the type, because you don't have access to the underlying storage. |
Beta Was this translation helpful? Give feedback.
-
I could only see this useful if you could reference any visible property in the .net framework. for example most properties in the framework would not be reference properties so this feature as it stand wouldn't be useful
|
Beta Was this translation helpful? Give feedback.
-
Properties are not necessarily backed by fields, this is not possible. C# 7 added ref returns, which makes this perfectly valid C# code: class C
{
private int _i;
public ref int P { get => ref _i; }
}
Nevermind, I see that the separate accessor is exactly the point of this proposal. Reopening. |
Beta Was this translation helpful? Give feedback.
-
@Shadowblitz16 However, that might be dangerous, since it removes the abstraction properties have other storage, and once you add your own accessors, code that using I think adding public
Obviously not all proparties match these criteria, but a great deal of them do. Records are perfect candidates for this, but also advanced data structures, things that act as proxies over a storage location, and lazy properties. All the things that could be turned into a |
Beta Was this translation helpful? Give feedback.
-
At the moment, if we need to have a property with a setter, but also need to be able to get a readonly reference to the underlying value, the only way to do that is by declaring two properties - which is messy, as shown below. private Value _value;
public Value Value
{
get => _value;
set
{
_value = value;
// Do something else, like notify of a property change
}
}
public ref readonly ValueRef => ref _value; So, we end up with a Value and a ValueRef property. It would be cleaner to just have a single Value property like below. public Value Value
{
ref readonly => ref _value;
set
{
_value = value;
// Do something else, like notify of a property change
}
} |
Beta Was this translation helpful? Give feedback.
-
🤔
Well, maybe ref property shouldn't be used like this at all. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
The standard property accessors,
get
andset
, do not cover all operations that can be performed on a variable, because the "obtain reference" operation is missing. This proposes a newref
accessor that returns a user-defined reference with the type of the property.Auto-generated properties are a perfect example of its use, because they always have a concrete backing field, and perform no error checking:
This would be translated to something like this (without the metadata):
In cases where the underlying storage is permanent and permits any values, this combines the encapsulation and elegancy properties provide with the speed and semantics of fields.
This is also extending indexers with array-like semantics:
This class (with an added Write method) works as an extendable buffer with a top limit (unlimited if
List<byte[]>
is used) which can be addressed exactly like an array thanks to theref
accessor –ref byte b = ref buffer[0];
.Notice the redundant code in the indexer? Because both
get
andset
can be implemented using theref
accessor, they can be auto-generated:The accessors will be generated like this (pseudocode):
If the data stored by the class is not permanent (like
List<T>
with resizable arrays), the result of theref
accessor cannot be guaranteed to be correct when the array is resized, but the accessor can be still used as private:This way, the consumer cannot accidentally obtain a reference to an invalidated array, but code duplication is still prevented.
Optionally,
ref readonly
may be used instead ofref
to make the reference read-only (e.g. passable toin
parameters).As far as I know, no changes are needed to the metadata format since custom accessors are already possible (
.other
in CIL). The Reflection API would need to be updated with GetRefMethod (also obtainable via GetAccessors).Languages that only understand
get
andset
accessors would still profit from the compiler-generatedref_PropertyName
method (and would be able to implement it).There is a fundamental difference between a ref property and a ref accessor. Ref accessors preserve the original (non-ref) type of the property, allowing easier reflection, interface implementation, and compatibility with languages that don't support ref returns.
Beta Was this translation helpful? Give feedback.
All reactions