One option is to used enumerations instead. You first need to define an enumeration as a type. This enumeration can in turn be whatever primitive data type you want. If you add the pragma "qualified_only", you can make the code look much elegant. Say for instance you define a new type as:
{attribute 'qualified_only'}
TYPE E_State :
(
A := 0,
B := 1,
C := 2
) USINT;
END_TYPE
What you're basically saying here is that this is an enumeration that will take up 1 byte of space (as the base-type is USINT), and that if you want to use the enumeration it needs to be preceeded with the name of the enumeration (in this case "E_State"). Note that you don't need to explicitly declare the numbers here. If you don't write any numbers, the compiler will automatically assume the first one is zero and add one to each one following. So this will work as well:
{attribute 'qualified_only'}
TYPE E_State :
(
A,
B,
C
) USINT;
END_TYPE
You don't even need to declare the base-type. If you don't declare anything (so not writing USINT above), the compiler will automatically assume it's an INT.
Using this in a switch-case in a program or function block would make it look like this:
PROGRAM MAIN
VAR
eState : E_State;
END_VAR
Body:
CASE eState OF
E_State.A :
// Do something A
E_State.B :
// Do something B
E_State.C :
// Do something C
ELSE
// Do something
END_CASE