1

我正在开发用于管理任务的应用程序。每个任务都有自己的状态。并且每个状态都必须易于分配(例如 enum -- task1.status = statuses.started)。而且每个状态都必须知道它的显示颜色、名称等。所以它不能是简单的枚举(我需要类似 --task1.status.color 的东西)。我不想使用 switch,或者很多 ifs。一切都必须非常快(因为这将被迭代很多次)并且代码必须是干净的。

我做了什么:

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 status1 = new Status();
            status1.Type = StatusType.statusEnded;
            Color somecolor = status1.Type.color;

现在解决问题。一切正常,直到我 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。它应该只制作引用的副本,而不是静态对象的副本。

那么,如果没有静态值的地址,那么属性状态是什么?

4

1 回答 1

0

您的Status.Type财产不是静态的。当您 DeepClone 对象时,会创建一个新实例并将其分配给克隆的实例。

您有两种解决方法:

  1. 修改 DeepClone 以查找现有实例并将其分配给克隆,而不是创建副本
  2. 实现 IEquatable 并覆盖通常的嫌疑犯:GetHashCode、Equals、== 和 !=

#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
}
于 2013-02-09T17:04:53.077 回答