采用以下示例代码:
class Program
{
static void Main( string[] args )
{
Stack<Data> s = new Stack<Data>();
Data d = new Data( 10 );
s.Push( d );
d.Value = 20;
Console.ReadKey();
}
}
class Data
{
public int Value;
public Data( int value )
{
Value = value;
}
}
没有Data
struct
有什么方法可以阻止d
实例放入堆栈,使d.Value = 20
更新对象属性线?当d
被推入堆栈时,它的Value
属性被赋值为10
,但是当属性被修改时,它被更改为20
。有没有其他方法可以阻止结构或克隆类来阻止它?
我问这个是因为我正在写一个国际象棋引擎,作为搜索和评估的一部分,它需要在棋盘上移动棋子。将电路板放在堆栈上时,我可以创建子分析板,这会影响已经堆叠的电路板。
答案 0 :(得分:0)
没办法。由于您使用引用类型,它应该更改所有实例。如果您在我建议您使用Object.MemberwiseClone方法之前使用 Value 的简单类型。
<强>更新强>
这个实现怎么样:
static void Main(string[] args)
{
Stack<Data> s = new Stack<Data>();
Data d = new Data(10);
d.Freeze();
s.Push(d);
d.Value = 20;
Console.WriteLine("Frozen value : {0}", s.Pop().Value);
Console.WriteLine("actual value : {0}", d.Actual(data => data.Value));
Console.ReadKey();
}
class FreezableValue<T>
{
private T frozenValue;
private T actualValue;
private bool isFrozen;
public void Freeze()
{
isFrozen = true;
}
public T ActualValue
{
get
{
return actualValue;
}
set
{
this.actualValue = value;
if(!isFrozen)
frozenValue = value;
}
}
public T FrozenValue { get { return frozenValue; } }
}
class Data
{
private readonly FreezableValue<int> freezableValue;
private bool useActualValue;
public Data(int value)
{
freezableValue = new FreezableValue<int> { ActualValue = value };
useActualValue = true;
}
public void Freeze()
{
freezableValue.Freeze();
useActualValue = false;
}
public int Value
{
get { return useActualValue ? freezableValue.ActualValue : freezableValue.FrozenValue; }
set { freezableValue.ActualValue = value; }
}
public T Actual<T>(Func<Data, T> func)
{
useActualValue = true;
try
{
return func(this);
}
finally
{
useActualValue = false;
}
}
}
答案 1 :(得分:0)
没有可能的方法将Board
类转换为struct
因为它太大而且有很多引用类型所以我决定不使用Stack对象来存储国际象棋的实例板。
相反,我创建了一个BoardManager
静态类来将所有单独创建的棋盘存储在列表中,当我需要某个板时,我只需使用板的标识符来检索它。
答案 2 :(得分:-1)
您可以使您的类Data实现只读接口:
public interface IReadOnlyData {
int SomeInt { get;}
string SomeString {get;}
}
然后你的Stack可以是:
Stack<IReadOnlyData> stack = new Stack<IReadOnlyData>();