1

可能重复:
C# 中的两个枚举何时相等?

我有以下类作为简单状态机的一部分。

请注意,所有泛型类型参数都必须是枚举。这已在构造函数中强制执行(此处未显示)。

// Both [TState] and [TCommand] will ALWAYS be enumerations.
public class Transitions<TState, TCommand>: List<Transition<TState, TCommand>>
{
    public new void Add (Transition<TState, TCommand> item)
    {
        if (this.Contains(item))
            throw (new InvalidOperationException("This transition already exists."));
        else
            this.Add(item);
    }
}

// Both [TState] and [TCommand] will ALWAYS be enumerations.
public class Transition<TState, TCommand>
{
    TState From = default(TState);
    TState To  = default(TState);
    TCommand Command = default(TCommand);
}

public sealed class TransitionComparer<TState>:
    IComparer<TState>
{
    public int Compare (TState x, TState y)
    {
        int result = 0;

        // How to compare here since TState is not strongly typed and is an enum?
        //    Using ToString seems silly here.

        result |= x.From.ToString().CompareTo(y.From.ToString());
        result |= x.To.ToString().CompareTo(y.To.ToString());
        result |= x.Command.ToString().CompareTo(y.Command.ToString());

        return (result);
    }
}

以上确实可以编译,但我不确定这是否是处理作为泛型类型参数传入的枚举的正确方法。

注意:比较功能不需要记住排序。相反,它需要检查确切的重复项。

4

2 回答 2

3

注意:比较功能不需要记住排序。相反,它需要检查确切的重复项。

在这种情况下,您不应该实施IComparer<T>. 您应该正在实施IEqualityComparer<T>- 或者更简单地说,是 make Transitionimplement IEquatable<Transition>

请注意,据我们所见,您目前没有在其余代码中使用。TransitionComparer听起来你真的不需要为每个枚举值编写自己的比较代码——你只是想把它们结合起来。不幸的是枚举没有实现IEquatable<T>,这使得在没有装箱的情况下更难做到这一点——这对性能有多重要?

这是一个示例相等性实现Transition

public class Transition<TState, TCommand>
    : IEquatable<Transition<TState, TCommand>>
{
    // I assume in reality these are properties?
    TState From = default(TState);
    TState To  = default(TState);
    TCommand Command = default(TCommand);

    public override bool Equals(object other)
    {
        return Equals(other as Transition<TState, TCommand>);
    }

    public bool Equals(Transition<TState, TCommand> other)
    {
        if (other == null)
        {
            return false;
        }
        return From.Equals(other.From) &&
               To.Equals(other.To) &&
               Command.Equals(other.Command);
    }

    public int GetHashCode()
    {
        int hash = 17;
        hash = hash * 31 + From.GetHashCode();
        hash = hash * 31 + To.GetHashCode();
        hash = hash * 31 + Command.GetHashCode();
        return hash;
    }
}

编辑:为了避免为平等而装箱,我怀疑您要么需要某种委托来获取基础值(如果您需要支持具有不同基础类型的值,那将非常痛苦),或者可能使用Unconstrained Melody之类的东西,它使用IL 重写以在编译时强制执行约束,并允许您更有效地检查基于底层值的相等性。

于 2012-09-24T05:59:32.763 回答
-1

我什么也看不见

(int)(object)x.From.CompareTo((int)(object)y.From);

枚举是装箱的。我不知道如何避免这种情况。

于 2012-09-24T06:02:37.177 回答