Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it Possible to Return a Reference to a Variable in C#? [duplicate]

Can I return a reference to a double value for example?

This is what I want to do:

ref double GetElement() {    ......    // Calculate x,y,z    return ref doubleArray[x,y,z]; } 

To use it like this

void func() {    GetElement()=5.0; } 

It is like returning a double pointer in C++ ... I know that the way I wrote it is wrong.. but is there a correct way for doing it?

like image 220
Betamoo Avatar asked Dec 27 '10 23:12

Betamoo


People also ask

Can we return a local variable by reference?

You cannot return reference of local variable, by return statement function ends and memory attached to the local variable will be deleted or freed by the compiler.

Should I return a reference?

Summary: it's okay to return a reference if the lifetime of the object won't end after the call.

Why should we not return a reference or an address of a local variable?

The return statement should not return a pointer that has the address of a local variable ( sum ) because, as soon as the function exits, all local variables are destroyed and your pointer will be pointing to someplace in the memory that you no longer own.

What does return a reference mean?

It means you return by reference, which is, at least in this case, probably not desired. It basically means the returned value is an alias to whatever you returned from the function. Unless it's a persistent object it's illegal.


2 Answers

UPDATE: The desired feature is now supported in C# 7.


The CLR type system does support ref-returning methods, and I have written an experimental prototype of the C# compiler which supports the feature you want. (The prototype also implements ref-typed local variables, but ref-typed fields are illegal in the CLR type system.)

You have hit upon exactly the syntax I chose for the prototype, which means that either great minds think alike, or that fools never differ.

Though the prototype works quite nicely, it is very unlikely that this will make the bar to become a feature of the next version of the C# language. Very few customers want this feature, it is fairly expensive to implement, we have a list as long as your arm of more important features, and there are other ways to make this sort of thing work without adding this complexity to the type system. These are all huge "points against" doing the feature.

For example, you could make a pair of delegates:

struct Ref<T> {     private readonly Func<T> getter;     private readonly Action<T> setter;     public Ref(Func<T> getter, Action<T> setter)     {         this.getter = getter;         this.setter = setter;     }     public T Value { get { return getter(); } set { setter(value); } } }  var arr = new int[10]; var myref = new Ref<int>(()=>arr[1], x=>arr[1]=x); myref.Value = 10; Console.WriteLine(myref.Value); 

That is considerably slower than the same feature implemented with ref returns, but the benefit is that you can make a Ref<T> in places where ref is not legal. For example, you can store Ref<T> in a field, which you cannot do with a ref-returning method.

If you have a really awesome compelling scenario for why you need ref-returning methods, I would love to hear about it. The more real-world scenarios we have, the more likely it is that such a feature might get implemented in a hypothetical future version of the language.

See also related questions:

Can I use a reference inside a C# function like C++?

Why doesn't C# support the return of references?

and my blog post on the subject:

http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/

like image 75
Eric Lippert Avatar answered Sep 23 '22 13:09

Eric Lippert


Update

This feature has been added to C# 7. You can use syntax just like you posted in your question. For example:

double[,,] doubleArray = new double[10,10,10];  ref double GetElement() {    var (x,y,z) = (1,2,3);    return ref doubleArray[x, y, z]; } 

Eric Lippert's answer goes into detail. I would probably delete this answer, but as it's the accepted answer I cannot delete it.

Original Answer

Value types in C# are always passed by value. Objects always have their reference passed by value. This changes in "unsafe" code as Axarydax points out.

The easiest, safest way to avoid this constraint is to make sure that your double is attached to an object somehow.

public class MyObjectWithADouble {     public double Element {get; set;} // property is optional, but preferred. }  ... var obj = new MyObjectWithADouble(); obj.Element = 5.0 

I also want to remark that I'm a little confused about how you anticipate assigning a double to a three-dimensional array. You might want to clarify what you're going for.

I think I understand a little better what you're going for now. You want to return the location of the value in a given array, and then be able to change the value in that location. This pattern breaks some of the expected paradigms of C#, so I would suggest considering other ways to achieve what you're looking for. But if it really makes sense to do it, I'd do something more like this:

public class 3dArrayLocation {public int X; public int Y; public int Z;}  ...  public 3dArrayLocation GetElementLocation(...) {     // calculate x, y, and z     return new 3dArrayLocation {X = x, Y = y, Z = z} }  ...  var location = GetElementLocation(...); doubleArray[location.X, location.Y, location.Z] = 5.0; 
like image 23
StriplingWarrior Avatar answered Sep 25 '22 13:09

StriplingWarrior