我正在开发app来管理任务。每个任务都有自己的状态。并且每个状态都必须易于分配(例如enum - task1.status = statuses.started)。并且每个状态都必须知道它的displayColor,name等。所以它不能简单枚举(我需要类似 - task1.status.color)。我不想使用开关或许多ifs。 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";
}
}
...和几种任务类型(Taken,Started,Ended,Billing)更像是这样..
然后是状态类
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 status1 = new Status();
status1.Type = StatusType.statusEnded;
Color somecolor = status1.Type.color;
现在问题。 Everithing工作正常,直到我的deepClone对象任务。我的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.statusEnded。但我不明白为什么。 Status.Type不应仅包含对静态对象的引用吗?我这么做了。这就是为什么我不担心DeepCopy。它应该只制作引用的副本,而不是静态对象的副本。
那么如果没有静态值的地址,那么什么才能保存属性?
答案 0 :(得分:0)
您的Status.Type
属性不是静态的。当您DeepClone对象时,将创建一个新实例并将其分配给克隆实例。
你有两种解决方法:
#2的优点是你不必确保你的状态对象是不可变的单例(即保证只有一个实例,并且一旦创建它就永远不会被修改)。这是一个简单的编程模型,我怀疑它会影响你的应用程序的性能。
以下是实现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
}