Search code examples
c#xamarinxamarin.formsxamarin.androidxamarin.ios

How can I use switch in enum?


Here is an enum:

public enum Size
{
    Normal = 1,
    Small =2
}

Now the enum is working in Xamarin and I want it to return a different value on different platforms.

For example the Normal:

switch (Device.RuntimePlatform)
{
  case Device.iOS:
    return 1;
  case Device.Android:
    return 2;
  case Device.UWP:
  default:
    return 3;
}

I want to use the enum directly but not declare one more variable or void, just like the NamedSize property(https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/text/fonts) in Xamarin.

I mean, is there any way something just like:

public enum Size
{
    Normal =>{
        switch (Device.RuntimePlatform)
        {
          case Device.iOS:
            return 1;
          case Device.Android:
            return 2;
          case Device.UWP:
          default:
            return 3;
        }
    },
    Small=2
}

How can I achieve it? Thank you.


Solution

  • That's a really great question, and you are right that they have found a way to do it using Xamarin. I tried this little experiment that should work:

    Failed Trial 1 - Device.OnPlatform(0,2,1)-The essentially let you use a different value depending on the platform (iOS, Android, Windows). So I put this into my VS:

    public enum Size
    {
        Normal =  Device.OnPlatform(0,2,1),
        Small = true ? 1 : 0
    }
    

    But I got an error saying The expression being assigned to 'Size.Normal' must be constant. The reason is because an enum is just a class where each of the members are of type const, so they can only contain a constant value.

    Failed Trial 2 - So I tried instead using simple C# to see if providing different values is possible at all

    public static class Utils
    {
        public static int Size(int i)
        {
            return i;
        }
    }
    public enum Size
    {
        Normal =  Utils.Size(2),
        Small = true ? 1 : 0
    }
    

    And, as you'd expect, I got the same error saying The expression being assigned to 'Size.Normal' must be constant.

    But how is Xamarin doing it?

    So I went to the declaration of NamedSize's properties in Xamarin Forms, and as you can see, it is in fact a constant. Screenshot showing NamedSize property in Assembly Browser When they assign a NamedSize value to a variable, they are likely doing the check Enum.GetNames(typeof(NamedSize)) at that instance in the getter of the FontSize property, and if that's not null, they assign the font size variable values.

    So How can you achieve something similar?

    You can follow the route that Device takes and create a static class instead of using an enum, and then you'll be able to use it in the same way, as shown:

    public class Size
    {
        public static int Normal => Device.OnPlatform(0, 2, 1);
        public const int Small = 3; // Const if the value won't change
    }
    ...
    // Inside your View code
    label.FontSize = Size.Normal;
    

    PS: Device.OnPlatform is deprecated, so if you want to avoid it, you can do this:

    public static int Normal
    {
        get
        {
            switch (Device.RuntimePlatform)
            {
                case Device.iOS:
                    return 1;
                case Device.Android:
                    return 2;
                case Device.UWP:
                default:
                    return 3;
            }
        }
    }