在深度克隆时保留对静态类的引用
本文关键字:静态类 引用 保留 深度 | 更新日期: 2023-09-27 17:58:23
我正在开发用于管理任务的应用程序。每个任务都有自己的状态。每个状态都必须很容易分配(比如enum-task1.status.started)。每个状态都需要知道它的displayColor、名称等。所以它不能是简单的enum(我需要像--task1.stats.color这样的东西)。我不想用switch或很多if。Everithing必须非常快速(因为这将被迭代很多次),并且代码必须干净。
我做了什么:
public class BaseStatusType {
public Color color;
private string name;
public BaseStatusType() {
}
public override string ToString()
{
return "status" + name;
}
[Serializable]
public class Untaken : BaseStatusType
{
public Untaken()
{
color = Appname.Core.App.Default.statusUntaken;
name = "Untaken";
}
}
以及几种更像这样的任务类型(已执行、已开始、已结束、计费)。。
然后是状态类
public class Status
{
public BaseStatusType Type;
public Status()
{
this.Type = StatusType.statusUntaken;
}
}
以及最重要的静态部分。由于有了这个部分,它可以很容易地分配。
[Serializable]
public static class StatusType {
public static BaseStatusType.Untaken statusUntaken = new BaseStatusType.Untaken();
public static BaseStatusType.Taken statusTaken = new BaseStatusType.Taken();
public static BaseStatusType.Started statusStarted = new BaseStatusType.Started();
public static BaseStatusType.Ended statusEnded = new BaseStatusType.Ended();
public static BaseStatusType.Billing statusBilling = new BaseStatusType.Billing();
}
现在,所有状态都初始化一次,同时应用程序启动。并非每次都创建Status。在创建新任务时,会创建新的"状态",但它的"类型"仅被分配,而不是新建。
Status status1 = new Status();
status1.Type = StatusType.statusEnded;
Color somecolor = status1.Type.color;
现在来谈谈问题。一直工作得很好,直到我深度克隆对象任务。我的deepClone使用序列化/反序列化。这个问题可以这样描述:
Task task1 = new Task();
task1.Status.Type = StatusType.statusEnded;
Task task2 = new Task();
task2 = task1.DeepClone();
if (task1.Status.Type == StatusType.statusEnded) {
//this returns true
}
if (task2.Status.Type == StatusType.statusEnded)
{
//this returns false
}
if (task2.Status.Type.ToString() == StatusType.statusEnded.ToString())
{
//this returns true
}
这可能是因为它在DeepCopy时创建了自己的StatusType.statusEnd。但我不明白为什么。Status.Type不应该只保存对静态对象的引用吗?我很坚强。这就是为什么我不担心DeepCopy的原因。它应该只做引用的副本,而不是静态对象的副本。
那么,如果没有静态值的地址,什么会保留属性Status呢?
您的Status.Type
属性不是静态的。当您深度克隆对象时,会创建一个新实例并将其分配给克隆的实例。
你有两种方法:
- 修改DeepClone以查找现有实例并将其分配给克隆,而不是创建副本
- 实现IEquatable并覆盖常见的可疑项:GetHashCode、Equals、==和!=
#2的优点是,您不必确保您的状态对象是不可变的singleton(即,确保只有一个实例,并且在创建后永远不会修改它)。这是一个简单的编程模型,我怀疑它是否会对应用程序的性能产生丝毫影响。
以下是实现IEquatable接口的类的示例:
public class Identity : IEquatable<Identity>
{
public Guid UniqueIdentifier { get; set; }
public string Name { get; set; }
public bool IsEmpty
{
get { return UniqueIdentifier == Guid.Empty; }
}
#region Construction
public Identity()
{
}
public Identity( Guid uniqueIdentifier, string name )
{
UniqueIdentifier = uniqueIdentifier;
Name = name;
}
#endregion
public override string ToString()
{
return string.IsNullOrWhiteSpace( Name ) ? UniqueIdentifier.ToString() : Name;
}
#region IEquatable
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override bool Equals( object obj )
{
return Equals( obj as Identity );
}
public static bool operator ==( Identity left, Identity right )
{
if( ReferenceEquals( null, left ) )
return ReferenceEquals( null, right );
return left.Equals( right );
}
public static bool operator !=( Identity left, Identity right )
{
if( ReferenceEquals( null, left ) )
return !ReferenceEquals( null, right );
return !left.Equals( right );
}
public bool Equals( Identity other )
{
if( ReferenceEquals( null, other ) )
return false;
return ToString() == other.ToString();
}
#endregion
}