处理对象状态的适当方式?

时间:2011-12-15 14:38:22

标签: c# algorithm design-patterns

我们目前正在开发一个需要处理各种资产的应用程序(C#,。Net 4.0)。为了跟踪资产的状态,我们开发了一个“AssetState”类,它返回资产可以处于的各种状态:

/// <summary>
/// Represents the states an asset can be in.
/// </summary>
public class AssetState
{
    /// <summary>
    /// Initializes a new instance of the <see cref="AssetState"/> class.
    /// </summary>
    public AssetState()
    {
    }

    #region Properties

    /// <summary>
    /// Gets a normal asset state.
    /// </summary>
    public static AssetState None
    {
        get
        {
            return new AssetState();
        }
    }

    /// <summary>
    /// Gets a dirty asset state.
    /// </summary>
    public static AssetState Dirty
    {
        get
        {
            return new AssetState();
        }
    }

    (etc...)

    #endregion Properties

    #region Methods

    /// <summary>
    /// Overloaded operator used to combine two states into a new one.
    /// </summary>
    /// <param name="leftOperandState">The left operand in the equation.</param>
    /// <param name="rightOperandState">The right operand in the equation.</param>
    /// <returns>A new asset state, which is the AND combination of both operands, in the form of a list of states.</returns>
    public static List<AssetState> operator &(AssetState leftOperandState, AssetState rightOperandState)
    {
        if (leftOperandState == None && rightOperandState != None)
        {
            return new List<AssetState> { rightOperandState };
        }

        if (leftOperandState != None && rightOperandState == None)
        {
            return new List<AssetState> { leftOperandState };
        }

        if (leftOperandState == None && rightOperandState == None)
        {
            return new List<AssetState> { leftOperandState };
        }

        return new List<AssetState> { leftOperandState, rightOperandState };
    }

    /// <summary>
    /// Overloaded operator used to combine two states into a new one.
    /// </summary>
    /// <param name="leftOperandStates">The left operand in the equation.</param>
    /// <param name="rightOperandState">The right operand in the equation.</param>
    /// <returns>A new asset state, which is the AND combination of both operands, in the form of a list of states.</returns>
    public static List<AssetState> operator &(List<AssetState> leftOperandStates, AssetState rightOperandState)
    {
        var newAssetState = new List<AssetState>();   

        newAssetState.AddRange(leftOperandStates);
        newAssetState.Add(rightOperandState);

        return newAssetState;
    }

    #endregion Methods
}

“资产”类将包含AssetStates列表。因此,例如,项目可以被标记为“Dirty”和“CheckedOut”。当我们需要确定资产的状态时,我们只需遍历该列表并确定是否存在特定的状态(或状态集)。

In the Asset Class:

    /// <summary>
    /// Method which determines if the asset is in a particular state.
    /// </summary>
    public bool IsInState(AssetState assetState)
    {
        return States.Contains(assetState);
    }

    /// <summary>
    /// Method which determines if the asset is in a particular combination of states.
    /// </summary>
    public bool IsInStates(IEnumerable<AssetState> assetStates)
    {
        if (assetStates == null)
        {
            throw new ArgumentNullException("assetStates");
        }

        // Determine if this asset is in all the states requested.
        return assetStates.All(assetState => assetState != null && this.IsInState(assetState));
    }

有没有更好的方法来解决这个问题?我们开发的系统是否有任何重大缺陷,我们忽略了这些缺陷? (同时请记住,这里的代码不是最终的,而是草稿)。

2 个答案:

答案 0 :(得分:5)

看起来你最好使用带有Flags属性的枚举。看看here

使用Flags属性,您将能够使用&amp;和|运营商。这是一个例子:

// make a dirty & checked-out state
AssetState state = AssetState.Dirty | AssetState.CheckedOut;

// check if state contains Dirty
if ((state & AssetState.Dirty) != 0)
{
    // handle the dirty state
}

小心分配给枚举的值。它们应该是1,2,4,8,16等,否则您将无法使用逻辑运算符正确组合它们。

答案 1 :(得分:3)

要组合这么少的可能状态,请使用enum而不是类。

[Flags]
enum AssetState
{
    None = 0,
    Dirty = 1,
    CheckedOut = 2,
    RequiresAudit = 4
}
//Create new state for checked out and requires audit
AssetState state = AssetState.CheckedOut | AssetState.RequiresAudit;
//Set dirty without changing rest of state:
state |= AssetState.Dirty;
//Check if is "dirty":
bool isDirty = (state & AssetState.Dirty) != AssetState.None;
//Check if is "dirty" alternative method:
bool isDirty = state.HasFlag(AssetState.Dirty);

您还可以将常用组合的值添加到枚举定义中,例如CheckedOutAndDity = 3