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?


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/


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;

No, this is not possible in C#. You can only pass parameters by reference.

However, you could achieve the same result with a property:

double Element
{
    get { return doubleArray[x,y,z]; }
    set { doubleArray[x,y,z] = value; }
}

void func()
{
   Element = 5.0;
}

You could do it in unsafe code and have a method that returns a pointer to double:

unsafe double* GetElementP(){
...
}