C#,将一个布尔复制到另一个布尔(通过引用,而不是val)
我在这里的一堵砖墙旁。是否可以将一个布尔复制到另一个布尔的ref。考虑这个代码…C#,将一个布尔复制到另一个布尔(通过引用,而不是val),c#,.net,value-type,reference-type,C#,.net,Value Type,Reference Type,我在这里的一堵砖墙旁。是否可以将一个布尔复制到另一个布尔的ref。考虑这个代码… bool a = false; bool b = a; b现在是一个完全独立的bool,其值为false。如果我随后更改a,它将对b没有影响。是否可以通过ref使a=b?我该怎么做 非常感谢布尔是一种值类型,不能通过引用进行复制 否。由于bool是一种值类型,因此它将始终按值复制 最好的选择是将bool封装在一个类中-这将为它提供引用类型语义: public class BoolWrapper { pu
bool a = false;
bool b = a;
b现在是一个完全独立的bool,其值为false。如果我随后更改a,它将对b没有影响。是否可以通过ref使a=b?我该怎么做
非常感谢布尔是一种值类型,不能通过引用进行复制 否。由于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
这可能不是您想要的,但是如果您的场景需要调用一个函数来修改本地布尔值,那么您可以使用ref或out keyworkd
bool a = false;
F(ref a);
// a now equals true
...
void F(ref bool x)
{
x = true;
}
感谢@Reed的回答(+1)!他鼓励我采用一种更“通用”的解决方案
公共类ValueWrapper,其中T:struct
{
公共T值{get;set;}
public ValueWrapper(T值){this.value=value;}
}
只需将标志用作Nullable
或bool?
,并在传递给泛型方法的结构中设置这些标志。上面的ValueWrapper
类本质上就是Nullable
所做的。因此我猜您需要传递一个引用一个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);
然后像这样使用它:
void myTestCaller() {
foo(myBoolRef);
}
void foo(BoolRef b) {
bool c = b(); // get myBool
b(true); // set myBool to true
}
同样的技巧也适用于其他值类型,如int我曾经有过一个案例,我想让一个类更改另一个类的bool-请注意,有更好的方法来处理这种情况,但这是使用操作的概念证明
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();
}
公共类1
{
bool myBool{get;set;}
void changeBoolFunc(bool val){myBool=val;}
公共类别1()
{
动作changeBoolAction=changeBoolFunc;
myBool=true;
Console.WriteLine(myBool);//输出“True”
类别2 c2=新类别2(变更生效);
Console.WriteLine(myBool);//输出“False”
}
}
公共课2
{
公共类2(操作boolChanger){boolChanger(false);}
}
void Main()
{
Class1 c1=新的Class1();
}
回答的小扩展名。。。这允许您最终直接将其分配给所需的任何类型。因此:
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
// ...
}
ValueWrapper wrappedBool=新的ValueWrapper(true);
bool unwrapped=wrappedBool;//您可以将其直接指定为:
如果(wrappedBool){//或使用它,您将如何直接使用bool
// ...
}
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;
}
}
public类ValueWrapper
{
公共T值{get;set;}
公共价值包装器(){}
公共价值包装(T值){
这个。值=值;
}
公共静态隐式运算符T(ValueWrapper)
{
if(包装器==null){
返回默认值(T);
}
返回wrapper.Value;
}
}
重构为只引用a??您能解释一下需要这样一个东西的场景吗?为什么要这样做?如果您提供更多详细信息,可能有人会找到一种方法来做您真正想要的事情。您必须使用指针,但为什么要在托管环境中编程呢(.NET)…bool只是System.Boolean的快捷方式。它们是一样的。C#bool是一个系统。布尔值。它们是相同的,都是值类型。是的,和System。Boolean是值类型。见:的确如此。尽管我忍不住想知道为什么这样的事情首先是必要的……引用类型保证被引用的对象至少和引用的时间一样长。不提供这种保证的值类型通常存储在堆栈上,并在执行离开其声明范围时消失。允许创建对值类型的持久和混杂引用需要计算机在其作用域退出之前将变量从堆栈中复制,并将引用指向新的副本;理论上,系统可以通过多种方式实现这一点,但所有这些方式都会在任何变量离开作用域时增加巨大的开销。是否有理由将Value
设置为属性而不是字段?可以在字段上使用Interlocked.compareeexchange
,但不能在属性上使用。可能与ValueWrapper
无关,但肯定与ValueWrapper
@supercat有关我在数据绑定中使用此字段,因为它必须是一个属性我可以看到数据绑定的限制可能会迫使使用属性,尽管公共字段在没有明确要求属性的情况下提供了许多优势。也许一种合理的方法是公开一个publicValue
字段和一个由其支持的ValueAsProperty
属性?Nullable仍然是一种值类型,请参见定义:public struct Nullable,其中T:structI想知道为什么会被否决。我发现这个解决方案在一些情况下很有用。
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;
}
}