По сути двухмерный Enum? - PullRequest
0 голосов
/ 30 мая 2019

Не знаю, как это сформулировать, но у меня есть класс под названием Lane для разных полос дороги.

Lane состоит из двух частей - Direction (перечисление левого или правого или другого), а затемчисло, целое числоТаким образом, дорожки выглядят так: L1, L2, R1, R3 и т. Д.

Для каждой дорожки должен быть только один экземпляр класса дорожек.L1 не должен существовать дважды.

Из-за этого я хочу иметь возможность назначить Lane объекта так, как вы можете назначить enum, набрав Lane.L1 или Lane.R4 и т. Д. В настоящее время я должен использовать метод, которыйнаходит существующий объект Lane, соответствующий Lane, на которую я пытаюсь ссылаться.

Это способ сделать это лучше?Например, просто набрав lane = Lane.L1, кроме того, что у класса Lane есть частные конструкторы и вручную создайте открытый метод Getter для каждой возможной Lane и присвойте ссылки в статическом конструкторе для класса Lane?

Этотекущее состояние класса дорожек:

public enum Direction { INCREASING = 1, DECREASING = 2, BOTH = 3, OTHER = 4, UNSPECIFIED = 5 }
public class Lane : IComparable
{
    public Direction Direction;
    public int Number = 1;
    public Lane(Direction direction, int number = 1)
    {
        Direction = direction;
        Number = number;
    }

    public override string ToString()
    {
        if (Direction == Direction.UNSPECIFIED)
        {
            return Direction.AsCharLR().ToString();
        }
        return Direction.AsCharLR() + Number.ToString();
    }

    public override bool Equals(object obj)
    {
        if (obj is Lane)
        {
            Lane l = obj as Lane;
            return Direction == l.Direction && Number == l.Number;
        }
        return false;
    }

    public override int GetHashCode()
    {
        return (int)Direction * 100 + Number;
    }

    public static Lane Parse(char lane)
    {
        lane = char.ToUpper(lane);
        switch (lane)
        {
            case 'L':
            case 'I':
                return new Lane(Direction.INCREASING);
            case 'R':
            case 'D':
                return new Lane(Direction.DECREASING);
            case 'B':
                return new Lane(Direction.BOTH);
            case 'U':
                return new Lane(Direction.UNSPECIFIED);
            case 'O':
            default:
                return new Lane(Direction.OTHER);
        }
    }
    public static Lane Parse(string text)
    {
        Lane lane = Parse(text[0]);
        lane.Number = int.Parse(text.Substring(1));
        return lane;
    }

    public int CompareTo(object l)
    {
        return GetHashCode() - l.GetHashCode();
    }
}

Ответы [ 2 ]

1 голос
/ 30 мая 2019

Вы не можете делать то, что хотите, с enum, потому что это не похоже на то, что вы устанавливаете ограничение для части «число», и вы не можете определять или использовать новые перечисления во время выполнения.

Это может быть все, что вам нужно:

public static class Lanes
{ 
    private static readonly Dictionary<string, Lane> LanesDictionary = 
        new Dictionary<string, Lane>();

    public static Lane GetLane(Direction direction, int number)
    {
        var key = direction.ToString() + number;
        if (LanesDictionary.ContainsKey(key))
        {
            return LanesDictionary[key];
        }
        var lane = new Lane(direction, number);
        LanesDictionary.Add(key, lane);
        return lane;
    }
}

Теперь каждый раз, когда вы ссылаетесь на Lanes.GetLane(Direction.INCREASING, 4), вы всегда получаете одно и то же Lane. Если он еще не существует, он будет создан.

Это дает вам удобный и читаемый способ ссылки на данную полосу. Если по какой-то причине вы хотели сокращенное обозначение для некоторых дорожек - хотя, как уже упоминалось, вы не хотите жестко их кодировать (я бы тоже не стал) - вы можете сделать это:

public static Lane L4 { get; } = GetLane(Direction.INCREASING, 4);
1 голос
/ 30 мая 2019

Хорошо, вы сказали, что вам не нужны частные конструкторы, но что, если у вас есть общедоступные статические атрибуты, такие как следующие?:

public class Lane
{
    private Direction direction;
    private int number;

    public static Lane L1 = new Lane(Direction.INCREASING, 1);
    public static Lane L2 = new Lane(Direction.INCREASING, 2);
    //add more ...

    private Lane() { }

    private Lane(Direction d, int n)
    {
        this.direction = d;
        this.number = n;
    }

    public enum Direction
    {
        INCREASING = 1, DECREASING = 2, BOTH = 3, OTHER = 4, UNSPECIFIED = 5
    }
}

Таким образом, вы можете ввести lane = Lane.L1, и он всегда будет возвращать один и тот же экземпляр. Этого достаточно?

...