2009-09-16 9 views
10

Estoy en una pared de ladrillos aquí. ¿Es posible copiar un bool al ref de otro? Considera este código. . .C#, copia un bool a otro (por ref, no val)

bool a = false; 
bool b = a; 

b ahora es un bool totalmente separado con un valor de falso. Si posteriormente cambio a, no tendrá efecto en b. ¿Es posible hacer a = b por ref? ¿Como podría hacerlo?

Muchas gracias

+2

Refactor a una única referencia ?? –

+5

¿Puede explicar el escenario en el que necesitará algo así? – shahkalpesh

+0

¿por qué le gustaría hacer esto? si proporciona más detalles, tal vez alguien haga una manera de hacer lo que realmente desea. – Zack

Respuesta

0

Un bool es un tipo de valor y no pueden ser copiados por referencia.

+0

bool es solo un atajo para System.Boolean. Ellos son idénticos. –

+0

a C# bool es un System.Boolean. Son lo mismo y ambos son tipos de valores. – Zack

+0

Sí, y System.Boolean es un tipo de valor. Ver: http://msdn.microsoft.com/en-us/library/system.boolean.aspx –

28

No. Dado que bool es un tipo de valor, siempre se copiará por valor.

La mejor opción es envolver su bool dentro de una clase - esto le dará tipo de referencia semántica:

public class BoolWrapper 
{ 
    public bool Value { get; set; } 
    public BoolWrapper (bool value) { this.Value = value; } 
} 

BoolWrapper a = new BoolWrapper(false); 
BoolWrapper b = a; 
b.Value = true; 
// a.Value == true 
+2

De hecho. Aunque no puedo evitar preguntarme por qué algo así es necesario en primer lugar ... – Noldorin

+4

Los tipos de referencia garantizan que el objeto al que se hace referencia vivirá al menos tanto tiempo como la referencia. Los tipos de valor, que no ofrecen tal garantía, a menudo se almacenan en la pila y desaparecen tan pronto como la ejecución abandona el alcance de su declaración. Permitir que uno cree una referencia persistente y promiscua a un tipo de valor requeriría que la computadora copie la variable de la pila antes de que salga su alcance, señalando la referencia en la nueva copia; En teoría, existen varias maneras en que el sistema podría hacer eso, pero todas ellas agregarían una gran sobrecarga cada vez que cualquier variable dejara de tener alcance. – supercat

2

esto puede no ser lo que quiera, pero si su situación fuera tal que querías una función que llamó para modificar su booleano local, puede usar el ref o out keyworkd.

bool a = false; 

F(ref a); 
// a now equals true 

... 

void F(ref bool x) 
{ 
x = true; 
} 
10

Gracias a @Reed por su respuesta (+1)! ¡Me animó a una solución más "genérica" ​​! :)

public class ValueWrapper<T> where T : struct 
{ 
    public T Value { get; set; } 
    public ValueWrapper(T value) { this.Value = value; } 
} 
+0

¿Hay alguna razón para hacer 'Value' una propiedad en lugar de un campo? Uno puede usar cosas como 'Interlocked.CompareExchange' en los campos, pero no en las propiedades. Quizás no sea relevante para 'ValueWrapper ', pero ciertamente relevante para 'ValueWrapper '. – supercat

+0

@supercat Estoy usando este campo en DataBinding, porque debe ser una propiedad –

+0

. Puedo ver que las limitaciones de DataBinding pueden obligar al uso de una propiedad, aunque los campos públicos ofrecen muchas ventajas en casos donde una propiedad no es explícitamente requerido. Quizás un enfoque razonable sería exponer un campo público 'Value' y una propiedad' ValueAsProperty' respaldados por él. – supercat

-3

sólo tiene que utilizar las banderas como Nullable<bool> o bool? y establecer las de la estructura que se pasa al método genérico. La clase anterior ValueWrapper<T> es esencialmente exactamente lo que Nullable<T> hace.

+3

Nullable es todavía un tipo de valor, ver la definición: public struct Nullable donde T: struct – rfcdejong

0

Supongo que necesita pasar una referencia a bool, que no puede envolver con una clase 'BoolWrapper', porque el bool vive en un lugar que no puede o no desea modificar.

¡Se puede hacer!

Primera declarar lo que cualquier referencia bool se verá como

/// <summary> A reference to a bool.</summary> 
/// <param name="value">new value</param> 
/// <returns>Value of boolean</returns> 
public delegate bool BoolRef(bool? value = null); 

Ahora usted puede hacer una referencia a myBool como esto

bool myBool; // A given bool that you cannot wrap or change 
    private bool myBoolRef(bool? value) { 
     if (value != null) { 
      myBool = (bool)value; 
     } 
     return myBool; 
    } 

Y utilizar de esta manera:

void myTestCaller() { 
     foo(myBoolRef); 
    } 
    void foo(BoolRef b) { 
     bool c = b(); // get myBool 
     b(true); // set myBool to true 
    } 

El mismo truco funciona para otros tipos de valores, como int

+0

Me gustaría saber por qué esto se degrada. He encontrado esta solución útil en varios casos. – James

0

Tuve un caso en el que quería que una clase cambiara el bool de otra clase: tenga en cuenta que hay mejores formas de manejar esta situación, pero esta es una prueba de concepto con Actions.

public class Class1 
{ 
    bool myBool { get; set; } 
    void changeBoolFunc(bool val) { myBool = val; } 
    public Class1() 
    { 
     Action<bool> changeBoolAction = changeBoolFunc; 
     myBool = true; 
     Console.WriteLine(myBool); // outputs "True" 
     Class2 c2 = new Class2(changeBoolAction); 
     Console.WriteLine(myBool); // outputs "False" 
    } 
} 
public class Class2 
{ 
    public Class2(Action<bool> boolChanger) { boolChanger(false); } 
} 
void Main() 
{ 
    Class1 c1 = new Class1(); 
} 
4

pequeña extensión a Andrey's respuesta ... esto le permite asignar a cualquier tipo que desea en el extremo directamente.Por lo tanto:

 ValueWrapper<bool> wrappedBool = new ValueWrapper<bool>(true); 

     bool unwrapped = wrappedBool; // you can assign it direclty: 

     if (wrappedBool) { // or use it how you'd use a bool directly 
      // ... 
     } 

public class ValueWrapper<T> 
{ 

    public T Value { get; set; } 

    public ValueWrapper() { } 

    public ValueWrapper(T value) { 
     this.Value = value; 
    } 

    public static implicit operator T(ValueWrapper<T> wrapper) 
    { 
     if (wrapper == null) { 
      return default(T); 
     } 
     return wrapper.Value; 
    } 

} 

Cuestiones relacionadas