C#,如何通过引用而不是值将一个bool变量复制到另一个bool变量?

19

我在这里遇到了瓶颈。是否可以将一个bool复制到另一个的引用中?考虑以下代码...

bool a = false;
bool b = a;
b现在是一个完全独立的布尔型变量,值为false。如果我随后改变a,这不会影响到b。是否可能通过引用使a=b?我该如何做到这一点?
非常感谢。

2
重构代码,仅引用 a??。 - Austin Salonen
5
你能解释一下什么情况下会需要这样的东西吗? - shahkalpesh
为什么你想要这样做?如果你提供更多细节,也许有人会找到一种实现你真正想要的方法。 - Zack
1
你需要使用指针,但为什么要在托管环境下进行编程呢(.NET)... - manji
8个回答

44

不会。因为bool是一个值类型,它总是被按值复制。

最好的选择是将您的bool包装在一个类中 - 这将给它引用类型语义:

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 

3
的确如此。尽管我不禁想知道为什么一开始需要这样做…… - Noldorin
5
引用类型保证所引用的对象至少要和引用一样长寿。值类型则不提供此类保证,它们通常被存储在堆栈上,只要执行离开它们的声明范围,它们就会消失。如果允许将值类型创建一个持久且放荡不羁的引用,计算机需要在其作用域结束之前将变量从堆栈复制到其他地方,并将引用指向新的副本;理论上有多种方法系统可以做到这一点,但所有这些方法都会在任何变量离开作用域时添加巨大的开销。 - supercat

19

感谢@Reed的回答(+1)!他鼓励我提出更加“通用”的解决方案! :)

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

有没有理由将 Value 设为属性而不是字段?可以在字段上使用 Interlocked.CompareExchange 等东西,但不能在属性上使用。也许对于 ValueWrapper<System.Boolean> 不相关,但对于 ValueWrapper<System.Integer> 肯定相关。 - supercat
@supercat 我在数据绑定中使用这个字段,因为它必须是一个属性。 - Andrey Morozov
我可以看出,数据绑定的限制可能会迫使使用属性,尽管在不需要显式属性的情况下,公共字段提供了许多优势。也许一个合理的方法是公开一个公共的“Value”字段和一个由此支持的“ValueAsProperty”属性? - supercat

15

Andrey的答案进行小扩展...这可以让你直接将其分配给最终想要的任何类型。因此:

        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;
    }

}


7

这可能不是您想要的,但如果您的情况需要一个函数来修改本地的布尔值,您可以使用 ref 或 out 关键字。

bool a = false;

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

...

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

1

我猜想你需要传递一个 bool 的引用,但是你无法使用“BoolWrapper”类进行包装,因为该 bool 存在于你不能或不想修改的某个位置。

这是可以做到的!

首先声明任何 bool 引用将看起来像什么

/// <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);

现在你可以像这样引用myBool变量:

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

并像这样使用它:

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

同样的技巧也适用于其他值类型,例如int。


我很想知道为什么这个被踩了。我在几个案例中发现这个解决方案非常有用。 - James

0
我曾经遇到这样一个情况,我想让一个类去改变另一个类的布尔值 - 请注意,有更好的方法来处理这种情况,但这只是使用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();
}

0

bool 是一个值类型,不能通过引用进行复制。


bool仅是System.Boolean的快捷方式。它们是完全相同的。 - Reed Copsey
C#中的bool是System.Boolean。它们是相同的,都是值类型。 - Zack
是的,System.Boolean 是一个值类型。请参阅:http://msdn.microsoft.com/zh-cn/library/system.boolean.aspx - Adam Hughes

-3

只需将标志用作Nullable<bool>bool?,并在传递给通用方法的结构中设置这些标志。上面的ValueWrapper<T>类本质上就是Nullable<T>所做的。


4
Nullable<T>仍然是值类型,参见定义: public struct Nullable<T> where T : struct - rfcdejong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接