¿Es posible devolver una referencia a una variable en C #?

¿Puedo devolver una referencia a un valor doble, por ejemplo?

Esto es lo que quiero hacer:

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

Para usarlo así

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

Es como devolver un puntero doble en C ++ … Sé que la forma en que lo escribí está mal … ¿pero hay una forma correcta de hacerlo?

Los tipos de valores en C # siempre se pasan por valor. Los objetos siempre tienen su referencia aprobada por valor. Esto cambia en el código “inseguro” como señala Axarydax.

La manera más fácil y más segura de evitar esta restricción es asegurarse de que su doble esté unido a un objeto de alguna manera.

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

También quiero comentar que estoy un poco confundido acerca de cómo anticipas asignar un doble a una matriz tridimensional. Es posible que desee aclarar lo que está buscando.

Creo que entiendo un poco mejor por lo que estás yendo ahora. Desea devolver la ubicación del valor en una matriz determinada y luego puede cambiar el valor en esa ubicación. Este patrón rompe algunos de los paradigmas esperados de C #, por lo que sugiero considerar otras formas de lograr lo que estás buscando. Pero si realmente tiene sentido hacerlo, haría algo más como esto:

 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; 

ACTUALIZACIÓN: la característica deseada ahora es compatible con C # 7.


El sistema de tipo CLR admite métodos de devolución de ref y he escrito un prototipo experimental del comstackdor de C # que admite la función que desea. (El prototipo también implementa variables locales ref-tipadas, pero los campos ref-typed son ilegales en el sistema de tipo CLR).

Has acertado exactamente con la syntax que elegí para el prototipo, lo que significa que o las grandes mentes piensan igual, o que los tontos nunca difieren.

Aunque el prototipo funciona muy bien, es muy poco probable que esto haga que la barra se convierta en una característica de la próxima versión del lenguaje C #. Muy pocos clientes quieren esta característica, es bastante costosa de implementar, tenemos una lista siempre y cuando su arm de características más importantes, y hay otras maneras de hacer que este tipo de cosas funcionen sin agregar esta complejidad al sistema de tipos. Estos son todos grandes “puntos en contra” de hacer la función.

Por ejemplo, podría hacer un par de delegates:

 struct Ref { private readonly Func getter; private readonly Action setter; public Ref(Func getter, Action 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(()=>arr[1], x=>arr[1]=x); myref.Value = 10; Console.WriteLine(myref.Value); 

Eso es considerablemente más lento que la misma función implementada con devoluciones de ref, pero la ventaja es que puede hacer una Ref en lugares donde la referencia no es legal. Por ejemplo, puede almacenar Ref en un campo, que no puede hacer con un método de devolución de ref.

Si tiene un escenario convincente realmente impresionante para el motivo por el cual necesita métodos de devolución de referencias, me encantaría saberlo. Cuantos más escenarios del mundo real tengamos, más probable es que dicha característica se implemente en una versión futura hipotética del idioma.

Ver también preguntas relacionadas:

¿Puedo usar una referencia dentro de una función C # como C ++?

¿Por qué C # no admite la devolución de referencias?

y mi blog sobre el tema:

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

No, esto no es posible en C #. Solo puede pasar parámetros por referencia.

Sin embargo, puede obtener el mismo resultado con una propiedad:

 double Element { get { return doubleArray[x,y,z]; } set { doubleArray[x,y,z] = value; } } void func() { Element = 5.0; } 

Podrías hacerlo en código inseguro y tener un método que devuelva un puntero al doble:

 unsafe double* GetElementP(){ ... } 

Después de pensar un poco, ¿por qué no enviar el valor que se establecerá con la función de esta manera:

 void SetElement(double value) { ...... // Calculate x,y,z doubleArray[x,y,z]=value; } 

y úsala:

 void func() { SetElement(5.0); } 

Sin embargo, aún elegiré una de sus respuestas útiles …