2010-08-11 14 views
5

tengo este código:¿Cuál es el patrón de C# para realizar una acción en una serie de valores?

if (PsionTeklogix.Keyboard.Keyboard.GetModifierKeyState(Key.Orange) == KeyState.Lock) 
    PsionTeklogix.Keyboard.Keyboard.InjectKeyboardCommand(Function.Orange, 0, 0); 

if (PsionTeklogix.Keyboard.Keyboard.GetModifierKeyState(Key.Blue) == KeyState.Lock) 
    PsionTeklogix.Keyboard.Keyboard.InjectKeyboardCommand(Function.Blue, 0, 0); 

if (PsionTeklogix.Keyboard.Keyboard.GetModifierKeyState(Key.Shift) == KeyState.Lock) 
    PsionTeklogix.Keyboard.Keyboard.InjectKeyboardCommand(Function.Shift, 0, 0); 

if (PsionTeklogix.Keyboard.Keyboard.GetModifierKeyState(Key.Control) == KeyState.Lock) 
    PsionTeklogix.Keyboard.Keyboard.InjectKeyboardCommand(Function.Control, 0, 0); 

... 

y quiero refactorizar el código separar la definición de clave/función de las acciones . Key.xxx y Function.xxx no son del mismo tipo.

por ejemplo: en Python, yo podría simplemente hacer algo como:

keys = (
    (Key.Orange, Function.Orange), 
    (Key.Blue , Function.Blue), 
    (Key.Shift , Function.Shift), 
    ... 
    ) 

psi_key = PsionTeklogix.Keyboard.Keyboard 

for key, func in keys: 
    if psi_key.GetModifierKeyState(key) == KeyState.Lock): 
     psi_key.InjectKeyboardCommand(func, 0, 0) 

¿Cuál es "la manera correcta" de hacerlo en C#?

+0

@Jimmy: Me gusta cómo asumes que está asumiendo. Tal vez es nuevo? En cualquier caso, 'for' in C# no hará lo que está pidiendo.Él necesita usar 'foreach'. –

+0

Ojalá pudiéramos rechazar los comentarios porque @Jimmy Hoffa no es necesario por aquí. – JonH

+0

@Jimmy: soy consciente de foreach, pero estaba buscando una forma no verbosa para construir la matriz inicial. Y sí, soy un novato en C# (lo siento) – PabloG

Respuesta

13

Usted puede hacer algo muy similar:

Dictionary<Key, Function> keys = new Dictionary<Key, Function> 
{ 
    { Key.Orange, Function.Orange }, 
    { Key.Blue, Function.Blue } 
    ... 
}; 

foreach (var pair in keys) 
{ 
    if (Keyboard.GetModifierKeyState(pair.Key) == KeyState.Locked) 
    { 
     Keyboard.InjectKeyboardCommand(pair.Value, 0, 0); 
    } 
} 

Incluso se puede utilizar LINQ si quería:

foreach (var pair in keys.Where(pair => 
       Keyboard.GetModifierKeyState(pair.Key) == KeyState.Locked) 
{ 
    Keyboard.InjectKeyboardCommand(pair.Value, 0, 0); 
} 

Ahora, utilizando un Dictionary es algo extraño teniendo en cuenta que aquí no estamos buscando todo arriba. Si está usando .NET 4, puede usar una lista de tuplas en su lugar:

var keys = new List<Tuple<Key, Function>>() 
{ 
    Tuple.Of(Key.Orange, Function.Orange), 
    Tuple.Of(Key.Blue, Function.Blue), 
    ... 
}; 

y ajuste el bucle en consecuencia. Se podría utilizar un tipo anónimo, también:

var keys = new[] 
{ 
    new { Key = Key.Orange, Function = Function.Orange }, 
    new { Key = Key.Blue, Function = Function.Blue }, 
    ... 
}; 

Están todos básicamente actuando como formas de representación de pares clave/función :)

+1

Tenga en cuenta un posible problema con la implementación del 'Diccionario': no se garantiza que el orden de los pares ** fuera ** sea el mismo que el de los pares ** en**. Si este orden es importante, puede ser un problema. Sin embargo, dada la implementación actual (en .NET, no estoy seguro acerca de Mono), creo que * * devolverá los pares en el mismo orden en que se agregaron, ya que ninguno se elimina. –

+0

gracias, el tipo anónimo funciona bien! Las otras alternativas no están disponibles: estoy usando .NET CF 2, lo siento, no lo mencioné antes. – PabloG

+0

@P Papi: Creo que tienes razón en todos los aspectos, y definitivamente no se debe depender de eso. –

0

Se puede usar un Dictionary para esto.

Dictionary<Key, Function> map = new Dictionary<Key, Function>(); 

map.Add(Key.Orange, Function.Orange); 
map.Add(Key.Blue, Function.Blue); 
map.Add(Key.Shift, Function.Shift); 
map.Add(Key.Control, Function.Control); 

foreach(var pair in map) 
{ 
    if (PsionTeklogix.Keyboard.Keyboard.GetModifierKeyState(map.Key) == KeyState.Lock) 
    { 
     PsionTeklogix.Keyboard.Keyboard.InjectKeyboardCommand(map.Value, 0, 0); 
    } 
} 
1

Suponiendo clave y la función son las enumeraciones, también se podría tratar:

foreach (Key key in Enum.GetValues(typeof(Key))) 
{ 
    if (PsionTeklogix.Keyboard.Keyboard.GetModifierKeyState(key) == KeyState.Lock) 
    { 
     PsionTeklogix.Keyboard.Keyboard.InjectKeyboardCommand((Function)Enum.Parse(typeof(Function), key.ToString()), 0, 0); 
    } 
} 
1
using PsionTeklogix.Keyboard; /* assuming that's a namespace, */ 
           /* otherwise, you can optionally do: */ 
/* using Keyboard = PsionTeklogix.Keyboard.Keyboard; */ 

class Foo{ 
    static readonly Key[] keys = {Key.Orange, Key.Blue, Key.Shift, ...}; 
    static readonly Function[] functions = {Function.Orange, Function.Blue, Function.Shift, ...}; 

    static void Main(){ 
     for(int i = 0; i < keys.Length; i++) 
      if(Keyboard.GetModifierKeyState(keys[i]) == KeyState.Lock) 
       Keyboard.InjectKeyboardCommand(func, 0, 0); 
    } 
} 

alternativa, ya que parece que tanto Key y Function están enumeraciones, y se utiliza la misma Function nombre del valor enum para cada valor de enunciado Key, puede hacer algo como esto, que es un poco más bonito, si es un poco más lento:

static readonly string[] values = {"Orange", "Blue", "Shift", ...}; 

static void Main(){ 
    foreach(string value in values) 
     if(Keyboard.GetModifierKeyState((Key)Enum.Parse(typeof(Key), value)) == KeyState.Lock); 
      Keyboard.InjectKeyboardCommand((Function)Enum.Parse(typeof(Function), value), 0, 0); 
} 

Bien, tal vez no sea más bonito. Meh.

Pero, si los valores de de Key también son los mismos que los valores de Function (es decir, si (int)Key.Orange == (int)Function.Orange, etc.), entonces usted puede hacer algo como:

static readonly Key[] keys = {Key.Orange, Key.Blue, Key.Shift, ...}; 

static void Main(){ 
    foreach(Key key in keys) 
     if(Keyboard.GetModifierKeyState(key) == KeyState.Lock); 
      Keyboard.InjectKeyboardCommand((Function)key, 0, 0); 
} 

Ninguno de estos es un equivalente directo del código Python, lo que sería de la misma familia:

class KeyFunction{ 
    readonly Key  key; 
    readonly Function function; 

    public Key  Key  {get{return key;}} 
    public Function Function{get{return function;}} 

    public KeyFunction(Key key, Function function){ 
     this.key  = key; 
     this.function = function; 
    } 
} 

static readonly KeyFunction[] keyFunctions = { 
    new KeyFunction(Key.Orange, Function.Orange), 
    new KeyFunction(Key.Blue, Key.Blue), 
    new KeyFunction(Key.Shift, Key.Shift), 
    ... 
}; 

static void Main(){ 
    foreach(KeyFunction kf in keyFunctions) 
     if(Keyboard.GetModifierKeyState(kf.Key) == KeyState.Lock) 
      Keyboard.InjectKeyboardCommand(kf.Function, 0, 0); 
} 

Ese es el sol más detallado de todos, pero es el más flexible.

Cuestiones relacionadas