1

私はタスクを管理するためのアプリに取り組んでいます。すべてのタスクには独自のステータスがあります。また、すべてのステータスを簡単に割り当てることができる必要があります(enum --task1.status = statuses.startedなど)。そして、すべてのステータスはそのdisplayColor、名前などを知っている必要があります。したがって、単純な列挙型にすることはできません(--task1.status.colorのようなものが必要です)。私はスイッチ、または多くの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";

            }

        }

...そしていくつかのタスクタイプ(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;

そして今、問題に。オブジェクトタスクをdeepCloneするまで、Everithingは正常に機能します。私の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について心配していませんでした。静的オブジェクトのコピーではなく、参照のコピーのみを作成する必要があります。

では、静的な値へのアドレスがない場合、プロパティStatusを保持するものは何でしょうか。

4

1 に答える 1

0

あなたのStatus.Type財産は静的ではありません。オブジェクトをDeepCloneすると、新しいインスタンスが作成され、複製されたインスタンスに割り当てられます。

これを回避するには2つの方法があります。

  1. DeepCloneを変更して既存のインスタンスを検索し、コピーを作成する代わりにそれをクローンに割り当てます
  2. IEquatableを実装し、通常の容疑者をオーバーライドします:GetHashCode、Equals、==および!=

#2の利点は、ステータスオブジェクトが不変のシングルトンであることを保証する必要がないことです(つまり、インスタンスが1つだけであり、作成後に変更されないことを保証します)。これは単純なプログラミングモデルであり、アプリケーションのパフォーマンスに少しでも影響を与えるとは思えません。

以下は、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 に答える