0

I have code like this:

switch (array[0], array[1], array[2])
{
    case (EntityRoute.North, EntityRoute.West, EntityRoute.South):
        prohibitedRoute = EntityRoute.East;
        return true;
    
    case (EntityRoute.South, EntityRoute.West, EntityRoute.North):
        prohibitedRoute = EntityRoute.East;
        return true;
    
    case (EntityRoute.North, EntityRoute.East, EntityRoute.South):
        prohibitedRoute = EntityRoute.West;
        return true;
    
    case (EntityRoute.South, EntityRoute.East, EntityRoute.North):
        prohibitedRoute = EntityRoute.West;
        return true;
    
    case (EntityRoute.South, EntityRoute.East, EntityRoute.North):
        prohibitedRoute = EntityRoute.West;
        return true;
}

I want to make a system where the order of conditions is not strict. Is there any option to make this without writing additional cases? Please take into account that I'm using C# 8.0 because I'm working in Unity3D.

vvvvv
  • 25,404
  • 19
  • 49
  • 81

5 Answers5

2

There's no need for a switch statement. Try this instead:

EntityRoute[] all = new [] { EntityRoute.North, EntityRoute.East, EntityRoute.South, EntityRoute.West,  };
EntityRoute[] array = new [] { EntityRoute.East, EntityRoute.South, EntityRoute.North, };
EntityRoute prohibitedRoute = all.Except(array).First();
Console.WriteLine(prohibitedRoute.ToString());

That gives me:

West

You can even define all like this:

EntityRoute[] all = Enum.GetValues(typeof(EntityRoute)).Cast<EntityRoute>().ToArray();
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • This is a fine alternative when Flags cannot be used. – Cleptus Jul 30 '21 at 06:19
  • @Cleptus - Flags themselves are not often a good alternative. Inspecting a value with flags often gets quite messy. I think it's better to work with discrete values. – Enigmativity Jul 30 '21 at 06:26
  • Thanks, for your suggestion) `all` - not in this case because I have one more option `EntityRoute.None`. Your first suggestion is better for me, thanks again) – Arcueid D'athemon Jul 30 '21 at 07:55
  • 1
    @ArcueidD'athemon - You could do `all.Except(array.StartWith(EntityRoute.None)).First()`. – Enigmativity Jul 30 '21 at 07:56
  • @Enigmativity - I don't think it's necessary. Also, I don't like use Linq so often because in Unity this can lead to freezes or low performance. So I usually avoid making a deal with the collection, but here without collection not possible to create project logic. – Arcueid D'athemon Jul 30 '21 at 08:17
0

No, there is nothing similar to what you want (checking in a single switch several objects).

The closest thing is the switch expression introduced in c# 8.0, but that would not check multiple variables at the same time.

Check CSharphie's answer final advice on why, if you mark the enumeration as Flags, really do not need the switch statement.

Cleptus
  • 3,446
  • 4
  • 28
  • 34
  • [CSharphie's answer](https://stackoverflow.com/a/68586122/2265446) is made without taking into account the impossibility to use `[Flags]` or that flags will break other logic. The best solution was given [here](https://stackoverflow.com/a/68586253/15371143) – Arcueid D'athemon Jul 30 '21 at 08:24
0

You can use Tuple Patterns which is part of C# 8.0

As shown below

EntityRoute? prohibitedRoute = (array[0], array[1], array[2]) switch
        {
            (EntityRoute.North, EntityRoute.West, EntityRoute.South) => EntityRoute.East,
            (EntityRoute.South, EntityRoute.West, EntityRoute.North) => EntityRoute.East,
            (EntityRoute.North, EntityRoute.East, EntityRoute.South) => EntityRoute.West,
            (EntityRoute.South, EntityRoute.East, EntityRoute.North) => EntityRoute.West,
            _ => null
        };
Yogesh Naik
  • 102
  • 8
0

If you do not want to work with flags, you could also order your values before the actual check:

// Copy array to keep original values. Only needed if you need to access the original order later
var orderedArray = array.Copy();
Array.Sort(orderedArray);

switch (orderedArray[0], orderedArray[1], orderedArray[2])
{
    // Write your cases according to the values of your enum here
}

I think this solution is the answer to your actual question.

In your specific case I would prefer the solution of Enigmativity.

Sebastian
  • 1,569
  • 1
  • 17
  • 20
-2

Assuming this is an Enum and it is marked with Flags (technically its not necessary) you can do this:

[Flags]
public enum EntityRoute
{
   North = 1,
   East = 2,
   South = 4,
   West = 8
}

You have to make sure the values are unique though, so order of enum values doesnt matter, Noth | East | South is the same as East | North | South, so it can only appear once.

switch (array[0] | array[1] | array[2])
{
    case EntityRoute.North | EntityRoute.West | EntityRoute.South:
        prohibitedRoute = EntityRoute.East;
        return true;
            
    ....
}

Keep in mind this only works correctly if the Enum has set up proper values, that are powers of two.

However then you wouldn't need an array to store the values:

something = EntityRoute.South | EntityRoute.East;
...
something |= EntityRoute.South

I recommend you reading about the topic of flags enums in c#. https://stackoverflow.com/a/8480/1789202

Then you will eventually figure out that you wont even need this switch case, if you allways have 3 directions and the result is the missing one.

CSharpie
  • 9,195
  • 4
  • 44
  • 71
  • Really `switch (array[0] | array[1] | array[2])` would check one single value, the result of the bitwise operation, but this answer has really some value because of the "_really not needed_" final advice. – Cleptus Jul 30 '21 at 06:12
  • I know about `[Flags]` but my case can't be solved with this, because: 1. I need enum values with strict integers behind them. 2. I don't need values such as `North | South | West | East` because this will break route direction logic. – Arcueid D'athemon Jul 30 '21 at 08:01