2010-08-02 5 views
3

Я пытаюсь написать функцию в C#, которая примет два небольших значения int (диапазон 0-3) и вернет объект Color на основе этих значений. Проблема в том, что нет возможности программно определить цвет из двух значений, они относятся к типу светодиода и должны быть жестко закодированы.Сопоставьте два значения одному объекту

Простейший способ, которым я могу думать, - это массивное (16 случаев) if-else утверждение, которое будет проверять каждое значение, но это не похоже на очень элегантное решение. Есть ли лучший способ определить цвет?

ответ

2

Как насчет двухмерного массива объектов Color?

Color[,] colors = new[,] { 
    { Color.FromArgb(1, 2, 3), Color.FromArgb(3, 4, 5), Color.FromArgb(6, 7, 8), Color.FromArgb(9, 10, 11) }, 
    { Color.FromArgb(21, 22, 23), Color.FromArgb(23, 24, 25), Color.FromArgb(26, 27, 28), Color.FromArgb(29, 30, 31) }, 
}; 

Color color = colors[index1, index2]; 
+0

Если вы идете по маршруту массива, многомерный или неровный массив, безусловно, лучше, чем внедрение множителя вручную. Единственными минусами являются незначительные подсчеты для проверки правильности отображения и нулей, если требуется разреженное сопоставление. –

+0

Это действительно все, что мне нужно для моих целей, но мне также нравится предложение Мэтью. К сожалению, я работаю.NET 3.5, который не поддерживает класс Tuple. Спасибо вам всем. – Nate

1

В качестве более чистой альтернативы использованию if/else вы можете поместить значения цвета в массив и использовать два небольших значения int в качестве индексов в массиве.

2

Если вы хотите идти OO подход (лучше или хуже), вы можете использовать Tuple-> Color: отображение

Dictionary<Tuple<int, int>, Color> d = new Dictionary<Tuple<int, int>, Color>() 
{ 
    {Tuple.Create(2, 1), Color.Red}, 
    {Tuple.Create(1, 1), Color.Blue}, 
    {Tuple.Create(1, 2), Color.Green} 
}; 

Одно из преимуществ над 2-й массиве может быть разреженным без обнуляет. Вы также можете использовать инициализатор коллекции без инициализации в порядке индекса. Это вызовет очевидное значение ArgumentException во время инициализации, если вы попытаетесь использовать один и тот же кортеж для двух цветов.

+0

Не знаете, почему этот человек получает downvoted. Это единственное решение, которое правильно обрабатывает разреженность и является наиболее расширяемым из всех. Вы можете очень легко распространить это на 3-переменный случай, и вы можете легко увеличить или уменьшить диапазоны переменных (а также иметь разные диапазоны). Не достоин нисходящего движения. – drharris

-3

Предпочитаемый способ избежать кучу if else утверждений является использование Switch. Вы также можете использовать enum и присвоить INT значения, которые соответствуют вашему малому Интсу:

public enum ColorChoice 
{ 
    red = 01 //'01' instead of '1' to make clear your first digit is zero 
    blue = 02 
    green = 03 
    ...etc... 
] 
+2

Как это решить его проблему обработки двух входных аргументов для разрешения цвета? –

+0

@kirk Woll - В прошлый раз, когда я проверил, вы можете вызвать значение Enum по его индексу. Итак, ввод «0, 1» => «1» => ColorChoice.Red. Это на самом деле легче понять (и, следовательно, поддерживать), чем многие из решений, требующих фактического преобразования математики. – AllenG

+0

Вы можете отличить целое число к перечислению. Но вам нужно будет сделать математическое преобразование в какой-то момент. Например. как вы делаете 3,1 -> оранжевый. Основываясь на вашей схеме, она, по-видимому, будет оранжевой = 31, что требует математики (10 * x + y). Кроме того, вы должны отметить, что 01 фактически является восьмеричным литералом; это просто не влияет на результат * здесь *. Кроме того, перечисления C# не могут иметь никаких полей или методов, поэтому вам может понадобиться другое ColorChoice-> Color mapping. –

0

Я голосую перечисление для 16 цветов

enum Color 
{ 
    red = 0, 
    blue = 1 
} 

public Color GetColor(int v1, int v2) 
{ 
    int colorValue = v1 << 8; 
    colorValue |= v2; 
    return (Color)colorValue; 
} 
+0

Использует множитель действительно самый читаемый синтаксис? Я подозреваю, что это послало бы многих программистов на холмы. –

+0

Я мог бы поменять место вместо этого, но я подумал бы, что отпустил бы отдельный подмножество программистов. –

+0

-1 Что происходит, когда каждый диапазон переходит в 0-4? Вся инициализация перечисления изменяется, как и формула и все. Умный, но не практичный. – drharris

0

Как насчет:

static Color GetColor(int c1, int c2) 
{ 
    if (c1 > 3 || c1 < 0 || c2 > 3 || c2 < 0) 
    throw new ArgumentOutOfRangeException(); 

    var map = new Dictionary<string, Color> 
    { 
    {"00", Color.Black}, 
    {"10", Color.Red}, 
    {"20", Color.Blue}, 
    // etc, etc... 
    {"11", Color.DimGray}, 
    }; 

    var key = c1.ToString() + c2.ToString(); 
    return map[key]; 
} 
0

факт, что у вас есть эти два небольших целочисленных значения, которые объединяются, чтобы что-то означать (по крайней мере, цвет), предлагает мне, что для вас может быть смысл иметь структуру, предназначенную для инкапсуляции м.

Преимущество этого в том, что вы можете использовать структуру как ключ к словарю: методы Equals и GetHashCode должны уже работать адекватно.

Ниже приведен пример. Поскольку вы упомянули, что цвета не могут быть рассчитаны, я оставил комментарий, в котором должен быть заполнен словарь; вы можете сделать это жестко, но в идеале вы будете читать значения из файла или встроенного ресурса.

EDIT: обновленный мой пример struct является неизменным.

struct MyStruct 
{ 
    private byte _X; 
    private byte _Y; 

    public MyStruct(byte x, byte y) 
    { 
     _X = x; 
     _Y = y; 
    } 

    public byte X { get { return _X; } } 
    public byte Y { get { return _Y; } } 

    private static Dictionary<MyStruct, Color> _ColorMap; 

    static MyStruct() 
    { 
     _ColorMap = new Dictionary<MyStruct, Color>(); 

     // read color mapping from somewhere...perhaps a file specific to the type of LED 
    } 

    public Color GetColor() 
    { 
     return _ColorMap[this]; 
    } 
} 
Смежные вопросы