Este es un patrón que se me ocurrió que me encuentro usando bastante. Por lo general, en el caso de pasar propiedades como parámetros para usar en cualquier objeto del tipo padre, pero funciona igual de bien para una sola instancia.(No funciona para los tipos de valor alcance locales Tho)
public interface IValuePointer<T>
{
T Value { get; set; }
}
public class ValuePointer<TParent, TType> : IValuePointer<TType>
{
private readonly TParent _instance;
private readonly Func<TParent, TType> _propertyExpression;
private readonly PropertyInfo _propInfo;
private readonly FieldInfo _fieldInfo;
public ValuePointer(TParent instance,
Expression<Func<TParent, TType>> propertyExpression)
{
_instance = instance;
_propertyExpression = propertyExpression.Compile();
_propInfo = ((MemberExpression)(propertyExpression).Body).Member as PropertyInfo;
_fieldInfo = ((MemberExpression)(propertyExpression).Body).Member as FieldInfo;
}
public TType Value
{
get { return _propertyExpression.Invoke(_instance); }
set
{
if (_fieldInfo != null)
{
_fieldInfo.SetValue(_instance, value);
return;
}
_propInfo.SetValue(_instance, value, null);
}
}
}
Esto entonces se puede utilizar como tal
class Test
{
public int a;
}
void Main()
{
Test testInstance = new Test();
var pointer = new ValuePointer(testInstance,x=> x.a);
testInstance.a = 5;
int copyOfValue = pointer.Value;
pointer.Value = 6;
}
Aviso la interfaz con un conjunto más limitado de argumentos de plantilla, esto le permite pasar el puntero a algo que no tiene conocimiento del tipo padre.
Incluso se podría implementar otra interfaz sin argumentos plantilla que llama .ToString en cualquier tipo de valor (no se olvide el cheque nulo primero)
Para que esto funcione correctamente, el lenguaje/marco debe permitir que las ubicaciones de almacenamiento se declaren persistentes, retornables o efímeras, y solo permite guardar cosas de una clase de almacenamiento en una clase igual o más restrictiva. El valor de retorno de una función sería el más restrictivo de su clase de devolución declarada, o la clase de almacenamiento más restrictiva pasó a sus parámetros "retornables". Dichas reglas no serían útiles no solo con los parámetros 'ref', sino también con otros parámetros (de modo que el código podría pasar una referencia a un objeto de clase mutable a un método, y saber ... – supercat
... que cualquier mutación que pudiera cualquier resultado de eso estaría completo antes de que el método en cuestión regresara, por lo tanto, en muchas situaciones eliminando la necesidad de una copia defensiva). – supercat
+1 tu respuesta porque resuelve el problema de persistencia. Sin embargo, estoy un poco triste porque C# no tiene ningún mecanismo para almacenar los tipos de valores como referencia. Entiendo que esto podría complicar las cosas para el GC, pero hacer referencia a los tipos de valores realmente podría tener un gran impacto en las técnicas de codificación. –