You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was messing around trying to wrap my head around ref-locals and ref-returns and I stumbled upon this roadblock. Consider the example below:
// Our base. Value is just there as an example, there could be methods.interfaceBase{intValue{get;}}// An implementation of Base.structValueType:Base{publicintValue{get;}}classObj{privateValueType_value;// (Obviously) happens with readonly too>publicref ValueType Value =>ref _value;// Okpublicref Base Base =>ref _value;// Does not compile}
Or a little more contrived example so you can see the use case:
abstractclassObjBase{// Mutate **knows** Value is implemented, but does not know the actual type, and does not need to.publicsealedvoidMutate(intvalue){
Value.Value =value;}publicabstractref Base Value {get;}}sealedclassObj:ObjBase{privateValueType_value;publicoverrideref Base Value =>ref _value;// Won't compile}classProgram{staticvoidMain(String[]args){ObjBaseo=new Obj();
o.Mutate(5);
Console.WriteLine(o.Value.Value);// Should print 5.}}
(Please excuse the multiple editsI- it's night time)
Expected Behavior: I'm really not sure. Is this a limitation to the feature, or a design choice?
Actual Behavior: ref-returns and ref-locals do not allow downcasting the referenced object to one of its base classes or interfaces.
The text was updated successfully, but these errors were encountered:
Warpten
changed the title
[Question] Implicit casting in ref-returning methods (autogenerated getters and setters included)
[Question] Casting in ref-returning methods (autogenerated getters and setters included)
Nov 13, 2018
The expression ref _value is a reference to a value of type ValueType, not a reference to a value of type Base. To get the latter from the former you'd have to box it, and then it would no longer be a reference.
You can't even do this if ValueType were a class. If we allowed you to do this, you would be able to assign any Base to Obj.Base. But the variable it refers to can only hold a ValueType and not any other derived type of Base.
In short, what you're hoping to do would not be typesafe.
Ah, that makes sense, I hadn't considered this scenario. Anyways, coming back at it this morning, I realize now this can be worked around by declaring _value as Base and assigning default(ValueType) to it in Obj's constructor (or as an initializer):
publicinterfaceBase{intProperty{get;}}publicstructSuperA:Base{publicintProperty{get;}}publicabstractclassObjBase{publicabstractref Base Value {get;}}publicclassObj:ObjBase{privateBase_property=default(SuperA);// Boxing happens herepublicoverrideref Base Value =>ref _property;}
This still boxes once, but now I'm able to obtain a reference to the member, as an interface, and mutate it (boo!), since boxing is done at the assignment site. It's not as pretty as I'd like to, but it works well enough. Neat!
However, what about making Value in ObjBase return a ref readonly? This ensures that the caller can no longer reassign the object returned by reference, my understanding being that ref-readonly is basically the C equivalent of T& const. Consider the following gist:
However, I suppose this still runs into the "boxing ref-returns" situation when trying to make _property a member of type SuperA, and adding some obscure feature named "boxed reference returns" is probably not worth the effort for the use it would get.
Version Used: 15.7.5
Steps to Reproduce:
I was messing around trying to wrap my head around ref-locals and ref-returns and I stumbled upon this roadblock. Consider the example below:
Or a little more contrived example so you can see the use case:
(Please excuse the multiple editsI- it's night time)
Expected Behavior: I'm really not sure. Is this a limitation to the feature, or a design choice?
Actual Behavior: ref-returns and ref-locals do not allow downcasting the referenced object to one of its base classes or interfaces.
The text was updated successfully, but these errors were encountered: