Enum类型的通用签名

时间:2011-04-26 15:55:43

标签: c# generics enums

我在项目中定义了几种Enum类型,用于特定于对象的状态标识符:

  public enum ObjectAState
  {
    ObjectAAvailable,
    ObjectADeleteRequested,
    ObjectADeleted
  }
  public enum ObjectBState
  {
    ObjectBCreationRequested,
    ObjectBCreationFailed,
    ObjectBDeleteRequested,
    ObjectBDeleted
  }

任何使用ObjectA的人都只能引用ObjectA枚举,所有其他对象也是如此 - 它们的枚举是隔离的,这使它们更容易理解,因为不显示不适用于对象的状态(这这就是为什么我不只是将所有对象的所有状态都放在一个enum)中。

对于给定的状态,可以跟随零,一个或多个其他状态(在同一enum内);根据定义,也有一些国家无法遵循。例如,在ObjectA中,州可以从ObjectAAvailable过渡到ObjectADeleteRequested,从ObjectADeleteRequested过渡到ObjectADeleted,但不能直接从ObjectAAvailable过渡到ObjectADeleted。在每个对象中都有一个繁琐且重复的代码来强制执行有效的状态转换,我想用单个方法替换它。

作为测试,我这样做了:

Dictionary<ObjectAState, List<ObjectAState>> Changes = new Dictionary<ObjectAState, List<ObjectAState>>();

这是Dictionary通过ObjectAState作为密钥访问的,其中包含List个其他ObjectAState个值,表示填充的有效转换:

Changes.Add(ObjectAState.ObjectAAvailable, new List<ObjectAState> { ObjectAState.ObjectADeleteRequested });
Changes.Add(ObjectAState.ObjectAADeleteRequested, new List<ObjectAState> { ObjectAState.ObjectADeleted });
Changes.Add(ObjectAState.ObjectADeleted, null);

我的方法看起来像这样:

public bool StateTransitionIsValid(ObjectAState currentState, ObjectAState targetState)
{
  return Changes[currentState].Contains(targetState);
}

这非常有效 - ObjectA的用户只需传入对象的当前和目标状态的enum,并获得一个简单的true或false,表示转换是否有效。那么,如何使这个通用,以便相同的方法可以处理来自其他对象的枚举?

我试过了:

Dictionary<Enum, List<Enum>> Changes = new Dictionary<Enum, List<Enum>>();

它编译时没有错误 - 但是向Dictionary添加条目的代码失败了:

Changes.Add(ObjectAState.ObjectAAvailable, new List<ObjectAState> { ObjectAState.ObjectADeleteRequested });

Error   1   The best overloaded method match for 'System.Collections.Generic.Dictionary<System.Enum,System.Collections.Generic.List<System.Enum>>.Add(System.Enum, System.Collections.Generic.List<System.Enum>)' has some invalid arguments
Error   2   Argument 2: cannot convert from 'System.Collections.Generic.List<MyApp.ObjectAState>' to 'System.Collections.Generic.List<System.Enum>'

我有一次狩猎,似乎无法看到我做错了什么。任何人都知道为什么我的'通用'版本无法编译?

2 个答案:

答案 0 :(得分:3)

您的方法或类必须一般定义,以便您可以使用实际的泛型类型。

难点在于无法在编译时完全强制泛型类型是枚举。这可能是你最接近的地方:

public class MyTestClass<T>
    where T : struct, IConvertible // Try to get as much of a static check as we can.
{
    // The .NET framework doesn't provide a compile-checked
    // way to ensure that a type is an enum, so we have to check when the type
    // is statically invoked.
    static EnumUtil()
    {
        // Throw Exception on static initialization if the given type isn't an enum.
        if(!typeof (T).IsEnum) 
            throw new Exception(typeof(T).FullName + " is not an enum type.");
    }

    Dictionary<T, List<T>> Changes = new Dictionary<T, List<T>>();
    ...
}

答案 1 :(得分:1)

我认为这是因为您尝试使用非通用对象,尽管该定义是通用的。试试这个。

Changes.Add(ObjectAState.ObjectAAvailable, new List<Enum> { ObjectAState.ObjectADeleteRequested });