I'm trying to implement a web interface for a user database. Hosts can create guests for their courses, the guests can get deleted after the course has ended but have to remain in the database for a given amount of time. If a host tries to create a guest that already exists in the database, the following things can happen:
- The guest is already active and was created by the same host,
- The guest is already active and was created by a different host,
- The guest is in deleted state and was created by the same host,
- The guest is in deleted state and was created by a different host.
Currently, I'm trying to represent the user state in this enum:
public enum GuestUserStatus
{
Unknown = 0,
NewGuest = 1,
ActiveSameHost = 10,
ActiveDifferentHost = 11,
DeletedSameHost = 20,
DeletedDifferentHost = 21
}
This allows me to switch() on the set user state.
However, to set the user state, I'm currently using repetetive if clauses like these:
if (queriedUser.GuestDetails.Creator == creator)
{
if (queriedUser.GuestDetails.State == GuestState.Deleted)
{
currentStatus = GuestUserStatus.DeletedSameHost;
}
else
{
currentStatus = GuestUserStatus.ActiveSameHost;
}
}
else
{
if (queriedUser.GuestDetails.State == GuestState.Deleted)
{
currentStatus = GuestUserStatus.DeletedDifferentHost;
}
else
{
currentStatus = GuestUserStatus.ActiveDifferentHost;
}
}
The nested if clauses act on the same condition but with a different outcome.
Is there a way to avoid this? I looked into marking the enum with [Flags] and using powers of 2 as underlying values, but then I couldn't use the switch() anymore.
UPDATE: Please note that I have the same conditions twice and different outcomes to them.
UPDATE2: Trying to address the linked question How to tackle a 'branched' arrow head anti-pattern?: Let's say I implement the accepted answer of that question. That would give me something like this:
bool activeSameHost = (queriedUser.Guest.Creator == creator && queriedUser.GuestDetails.State != GuestState.Deleted);
bool activeDifferentHost = (queriedUser.Guest.Creator == creator && queriedUser.GuestDetails.State == GuestState.Deleted);
bool inactiveSameHost = (queriedUser.Guest.Creator != creator && queriedUser.GuestDetails.State == GuestState.Deleted);
bool inativeDifferentHost = (queriedUser.Guest.Creator != creator && queriedUser.GuestDetails.State == GuestState.Deleted);
if(activeSameHost) currentStatus = GuestUserStatus.ActiveSameHost;
if(inactiveSameHost) currentStatus = GuestUserStatus.InactiveSameHost;
if(activeDifferentHost) currentStatus = GuestUserStatus.ActiveDifferentHost;
if(inactiveDifferentHost) currentStatus = GuestUserStatus.InactiveDifferentHost;
I fail to see the improvement. Sure, the ifs are no longer nested, but the only thing that changed is the complexity moving from the nested ifs to the assignment of intermediate variables.
switchand[Flags]cannot be used together? You can writecase GuestUserStatus.Deleted | GuesUserStatus.SameHost:, and you can also defineDeletedSameHost = Deleted | SameHostin yourenumdeclaration. – jhominal Mar 10 '15 at 08:54switchif using the bitwise OR:case GuestUserStatus.Deletedwill be evaluated and call an action, a latercase GuestUserStatus.Deleted | GuestUserStatus.SameHostwill be called too. Won't it? – Thaoden Mar 10 '15 at 08:58case GuestUserStatus.Deleted:will only be executed if the value is exactly equal toDeleted, andcase GuestUserStatus.Deleted | GuestUserStatus.SameHost:will only be called if the value is exactly equal toDeleted | SameHost, because in effect it iscase (GuestUserStatus.Deleted | GuestUserStatus.SameHost):. – jhominal Mar 10 '15 at 09:01switchremained the way it was and the nested ifs vanished into nothingness. Thanks! – Thaoden Mar 10 '15 at 09:12switching on the enum, I have toif-test both on the to be implemented host class and the to be implemented state class. Again, it's only moving complexity around. As per my requirements (see question), I need both informations inside my queriedUser. – Thaoden Mar 11 '15 at 10:22