I have Unity 2021 so it uses C# version > 7 I believe. Somehow I can not use static objects in Switch/Case statement.
private Position getStartingPosition(Direction direction) {
switch (direction) {
case Direction Direction.EAST:
return new Position(-1, height / 2);
case Direction Direction.NORTH:
return new Position(width / 2, height);
case Direction Direction.WEST:
return new Position(width, height / 2);
case Direction Direction.SOUTH:
return new Position(width / 2, -1);
default:
throw new System.Exception("Impossible");
}
}
and the Direction class:
public class Direction
{
static public readonly Direction EAST = new Direction(1, 0);
static public readonly Direction NORTH = new Direction(0, -1);
static public readonly Direction WEST = new Direction(-1, 0);
static public readonly Direction SOUTH = new Direction(0, 1);
...
The error I am getting is:
Grid.cs(38,31): error CS1003: Syntax error, ':' expected
Grid.cs(38,31): error CS1513: } expected
Grid.cs(38,36): error CS1003: Syntax error, ':' expected
Grid.cs(38,36): error CS1513: } expected
Grid.cs(40,31): error CS1003: Syntax error, ':' expected
Grid.cs(40,31): error CS1513: } expected
What am I doing wrong?
CodePudding user response:
The case
statment should be var _ when direction.Equals(Class.VALUE)
without the declaration. But also Direction
is an object so one option can be use this statment:
switch (direction) {
case var _ when direction.Equals(Direction.EAST):
return new Position(-1, height / 2);
case var _ when direction.Equals(Direction.NORTH):
return new Position(width / 2, height);
case var _ when direction.Equals(Direction.WEST):
return new Position(width, height / 2);
case var _ when direction.Equals(Direction.SOUTH):
return new Position(width / 2, -1);
default:
throw new System.Exception("Impossible");
}
And implement the interface IEquatable<Direction>
with a method similar to this:
public bool Equals(Direction otherDirection)
{
return (this.x == otherDirection.x && this.y == otherDirection.y);
}
Where x
and y
are values into your class used to know if two objects are equals.
CodePudding user response:
Was already answered here: Switch statement with static fields
I changed it to
switch (direction) {
case var _ when direction == Direction.EAST:
return new Position(-1, height / 2);
case var _ when direction == Direction.NORTH:
return new Position(width / 2, height);
case var _ when direction == Direction.WEST:
return new Position(width, height / 2);
case var _ when direction == Direction.SOUTH:
return new Position(width / 2, -1);
default:
throw new System.Exception("Impossible");
}
CodePudding user response:
Unity uses C# 9.0. You can only switch on constants and patterns (where a constant is a constant pattern).
We can use a positional pattern to do the test. To use it we must add a deconstructor to the class
public class Direction
{
public Direction(int east, int south)
{
East = east;
South = south;
}
public int East { get; }
public int South { get; }
public void Deconstruct(out int east, out int south)
{
east = East;
south = South;
}
}
Then we can switch like this:
switch (direction) {
case (1, 0):
return new Position(-1, height / 2);
case (0, -1):
return new Position(width / 2, height);
case (-1, 0):
return new Position(width, height / 2);
case (0, 1):
return new Position(width / 2, -1);
default:
throw new ArgumentException("Impossible", nameof(direction));
}
Another possible pattern is the tuple pattern not requiring a deconstructor:
switch ((direction.East, direction.South)) {
case (1, 0):
return new Position(-1, height / 2);
case (0, -1):
return new Position(width / 2, height);
case (-1, 0):
return new Position(width, height / 2);
case (0, 1):
return new Position(width / 2, -1);
default:
throw new ArgumentException("Impossible", nameof(direction));
}
Yet another possibility is to switch on enum
constants using a constant pattern:
public enum DirectionKind
{
None,
East,
North,
West,
South
}
We then add a property like the following one to the Direction
class
public DirectionKind DirectionKind { get; }
I leave it up to you to initialize it. Then we switch like this:
switch (direction.DirectionKind) {
case DirectionKind.East:
return new Position(-1, height / 2);
case DirectionKind.North:
return new Position(width / 2, height);
case DirectionKind.West:
return new Position(width, height / 2);
case DirectionKind.South:
return new Position(width / 2, -1);
default:
throw new ArgumentException("Impossible", nameof(direction));
}
Finally, let's use a property pattern:
switch (direction) {
case { East: 1, South: 0 }:
return new Position(-1, height / 2);
case { East: 0, South: -1 }:
return new Position(width / 2, height);
case { East: -1, South: 0 }:
return new Position(width, height / 2);
case { East: 0, South: 1 }:
return new Position(width / 2, -1);
default:
throw new ArgumentException("Impossible", nameof(direction));
}
Since C# 9.0 we have the switch expression with a simplified syntax compared to the switch statement:
// Positional pattern with deconstructor
return direction switch {
( 1, 0) => new Position(-1, height / 2),
( 0, -1) => new Position(width / 2, height),
(-1, 0) => new Position(width, height / 2),
( 0, 1) => new Position(width / 2, -1),
_ => throw new ArgumentException("Impossible", nameof(direction)),
};
// Tuple pattern
return (direction.East, direction.South) switch {
( 1, 0) => new Position(-1, height / 2),
( 0, -1) => new Position(width / 2, height),
(-1, 0) => new Position(width, height / 2),
( 0, 1) => new Position(width / 2, -1),
_ => throw new ArgumentException("Impossible", nameof(direction)),
};
// Constant pattern on enum constants
return direction.DirectionKind switch {
DirectionKind.East => new Position(-1, height / 2),
DirectionKind.North => new Position(width / 2, height),
DirectionKind.West => new Position(width, height / 2),
DirectionKind.South => new Position(width / 2, -1),
_ => throw new ArgumentException("Impossible", nameof(direction)),
};
// Property pattern
return direction switch {
{ East: 1, South: 0 } => new Position(-1, height / 2),
{ East: 0, South: -1 } => new Position(width / 2, height),
{ East: -1, South: 0 } => new Position(width, height / 2),
{ East: 0, South: 1 } => new Position(width / 2, -1),
_ => throw new ArgumentException("Impossible", nameof(direction)),
};
With target typed new we can write (with the positional pattern as an example):
return direction switch {
( 1, 0) => new (-1, height / 2),
( 0, -1) => new (width / 2, height ),
(-1, 0) => new (width, height / 2),
( 0, 1) => new (width / 2, -1 ),
_ => throw new ArgumentException("Impossible", nameof(direction)),
};