Enum 类型的通用签名
我在我的项目中定义了几种 Enum
类型,用于特定于对象的状态标识符:
public enum ObjectAState
{
ObjectAAvailable,
ObjectADeleteRequested,
ObjectADeleted
}
public enum ObjectBState
{
ObjectBCreationRequested,
ObjectBCreationFailed,
ObjectBDeleteRequested,
ObjectBDeleted
}
任何使用 ObjectA 的人只能引用 ObjectA 枚举,所有其他对象也是如此 - 它们的枚举是隔离的,这使得它们更容易理解,因为不显示不适用于对象的状态(这就是为什么我不只是将所有对象的所有状态放在一个枚举
中)。
对于给定的状态,可以有零个、一个或多个其他状态(在同一个enum
内);根据定义,也有某些国家无法遵循。例如,在 ObjectA
中,状态可以从 ObjectAAvailable
转换到 ObjectADeleteRequested
,以及从 ObjectADeleteRequested
转换到 ObjectADeleted
,但不是直接从 ObjectAAvailable
到 ObjectADeleted
。在每个对象中都有一些乏味且重复的代码来强制执行有效的状态转换,我想用一个方法来替换它们。
作为测试,我这样做了:
Dictionary<ObjectAState, List<ObjectAState>> Changes = new Dictionary<ObjectAState, List<ObjectAState>>();
这是一个通过 ObjectAState
作为键访问的 Dictionary
,包含其他 ObjectAState< 的
List
/code> 值表示有效的转换,如下所示:
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>>();
它编译时没有错误 - 但是向字典添加条目的代码失败了:
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>'
我四处寻找,似乎看不出我做错了什么。有人知道为什么我的“通用”版本无法编译吗?
I have several Enum
types defined across my project, used for object-specific state identifiers:
public enum ObjectAState
{
ObjectAAvailable,
ObjectADeleteRequested,
ObjectADeleted
}
public enum ObjectBState
{
ObjectBCreationRequested,
ObjectBCreationFailed,
ObjectBDeleteRequested,
ObjectBDeleted
}
Anyone using ObjectA can only refer to ObjectA enums, and the same is true of all the other objects - their enums are isolated, and this makes them easier to understand since states which are not applicable to an object are not shown (this is why I don't just put all the states for all objects in a single enum
).
For a given state, there are zero, one or many other states (within the same enum
) which can follow; by definition, there are also certain states which cannot follow. In ObjectA
, for example, the state can transition from ObjectAAvailable
to ObjectADeleteRequested
, and from ObjectADeleteRequested
to ObjectADeleted
, but not directly from ObjectAAvailable
to ObjectADeleted
. In each object there is a tedious and repetitive bit of code to enforce valid state transitions, which I want to replace with a single method.
As a test, I did this:
Dictionary<ObjectAState, List<ObjectAState>> Changes = new Dictionary<ObjectAState, List<ObjectAState>>();
This is a Dictionary
accessed via ObjectAState
as a key, holding a List
of other ObjectAState
values which indicate valid transitions populated thus:
Changes.Add(ObjectAState.ObjectAAvailable, new List<ObjectAState> { ObjectAState.ObjectADeleteRequested });
Changes.Add(ObjectAState.ObjectAADeleteRequested, new List<ObjectAState> { ObjectAState.ObjectADeleted });
Changes.Add(ObjectAState.ObjectADeleted, null);
And I have a method which simply looks like this:
public bool StateTransitionIsValid(ObjectAState currentState, ObjectAState targetState)
{
return Changes[currentState].Contains(targetState);
}
This works perfectly - users of ObjectA simply pass in the enum
of the current and target states of the object and get a simple true or false for whether the transition is valid. So, how to make this generic so that the same method can handle enums from other objects?
I tried this:
Dictionary<Enum, List<Enum>> Changes = new Dictionary<Enum, List<Enum>>();
It compiles without error - but the code which adds entries to the Dictionary fails:
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>'
I've had a hunt around and can't seem to see what I'm doing wrong. Anyone got any ideas why my 'generic' version doesn't compile?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的方法或类必须是通用定义的,以便您可以使用实际的通用类型。
困难在于没有办法在编译时完全强制泛型类型是 Enum。这可能是您最接近的:
Your method or class must be generically defined, so that you have an actual generic type to work with.
The difficulty is that there is no way to fully enforce that the generic type is an Enum at compile time. This is probably the closest you'll come:
我认为这是因为您尝试使用非通用对象,尽管定义是通用的。试试这个。
I think it's because you are trying to use a non generic object although the definition was generic. try this.