2009-05-22 20 views
6

Debido a que este es mi primer intento de un método de extensión que parece bastante útil para mí, sólo quiero para asegurarse de que voy por el camino de la derechaMi primer método de extensión, ¿podría escribirse mejor?

public static bool EqualsAny(this string s, string[] tokens, StringComparison comparisonType) 
    { 
     foreach (string token in tokens) 
     { 
      if (s.Equals(token, comparisonType)) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

Llamado por

if (queryString["secure"].EqualsAny(new string[] {"true","1"}, StringComparison.InvariantCultureIgnoreCase)) 
{ 
    parameters.Protocol = Protocol.https; 
} 

EDITAR: Algunas sugerencias excelentes que vienen, exactamente el tipo de cosa que estaba buscando. Gracias

EDIT:

me he decidido por la siguiente implementación

public static bool EqualsAny(this string s, StringComparison comparisonType, params string[] tokens) 
{ 
    // for the scenario it is more suitable for the code to continue 
    if (s == null) return false; 

    return tokens.Any(x => s.Equals(x, comparisonType)); 
} 

public static bool EqualsAny(this string s, params string[] tokens) 
{ 
    return EqualsAny(s, StringComparison.OrdinalIgnoreCase, tokens); 
} 

he preferido usar params sobre IEnumerable porque simplifica el código de llamada

if (queryString["secure"].EqualsAny("true","1")) 
{ 
    parameters.Protocol = Protocol.https; 
} 

algo muy distinto de el anterior

if (queryString["secure"] != null) 
{ 
    if (queryString["secure"] == "true" || queryString["secure"] == "1") 
    { 
     parameters.Protocal = Protocal.https; 
    } 
} 

¡Gracias de nuevo!

+0

personalmente, creo que usted debe hacer una pregunta preliminar antes de preguntarse sobre la sintaxis del método de extensión: no vas a querer este método. Primero, como otros lo han mencionado, es solo una inversión de tokens. Cualquier(), y en segundo lugar, en su ejemplo de uso, ha tomado un concepto simple de "es este un valor verdadero" que debería haber sido fácil de leer y reemplazar con una expresión compleja que implica un método de extensión personalizado y una matriz sobre la marcha. IMO, estos pequeños bits de complejidad innecesaria se suman. – tnyfst

Respuesta

5
public static bool EqualsAny(
    this string s, 
    StringComparison comparisonType, 
    params string[] tokens) 
{ 
    foreach (string token in tokens) 
    { 
     if (s.Equals(token, comparisonType)) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

Con params, no es necesario forzar primero las cadenas en una matriz.

var match = "loool".EqualsAny(StringComparison.Ordinal, "hurf", "Durf"); 

LINQ-cado (JC + me) con un (norma marco) NRE:

public static bool EqualsAny(
    this string s, 
    StringComparison comparisonType, 
    params string[] tokens) 
{ 
    if(s == null) throw new NullReferenceException("s"); 
    return tokens.Any(x=> s.Equals(x, comparisonType)); 
} 
2

Haga que su parámetro tokens sea más general, es decir, conviértalo en IEnumerable<string>.

Además, ya existe un método equivalente que se extiende a IEnumerable<>, p. Ej. Any:

public static bool EqualsAny(this string s, IEnumerable<string> tokens, StringComparison comparisonType) 
{ 
    return tokens.Any(t => s.Equals(t, comparisonType)); 
} 

Además, Joel es, por supuesto derecha: es posible que desee comprobar si hay null valores antes de realizar las acciones (codificación defensiva). Esto no es más seguro, pero hace que el error sea más fácil de localizar.

+0

@Joel: tienes razón. Estaba hablando en general acerca de * any * tipo de manejo de errores. Lanzar 'NullReferenceException' podría ser más apropiado. Como dijiste: no sabemos cuál es el comportamiento preferido aquí. –

+0

Eh, quise decir 'ArgumentNullException'. –

+0

Diría que sí, es definitivamente menos seguro, y posiblemente también más difícil de localizar, porque el código podría ejecutarse con una suposición falsa no válida durante mucho tiempo antes de que el error aparezca de manera visible. Lanzar una excepción puede ser más apropiado, pero no podemos saber qué comportamiento necesita el OP al escribir la muestra. Por lo tanto, para bien o para mal, el sesgo es proporcionar código que simplemente se ejecuta. –

1

con el fin de simplificar el uso de EqualsAny podría utilizar varargs y la estrategia predeterminada para StringComparison:

public static bool EqualsAny(this string s, params string[] tokens) { 
    return EqualsAny(s, StringComparison.InvariantCultureIgnoreCase, tokens); 
} 

public static bool EqualsAny(this string s, 
          StringComparison stringComparison, 
          params string[] tokens) { 
    // your method 
} 

llamado por

if (queryString["secure"].EqualsAny("true", "1")) { 
    parameters.Protocol = Protocol.https; 
} 
+0

params tiene que ser el último argumento. – Will

7

Sí! Primero, debe verificar s para nulo. Además, deje que se acepta ninguna IEnumerable<string> de fichas en lugar de sólo una matriz, y luego usar otros operadores LINQ para hacer el registro de entrada:

public static bool EqualsAny(this string s, IEnumerable<string> tokens, StringComparison comparisonType) 
{ 
    if (s== null) return false; 
    return tokens.Any(t => s.Equals(t, comparisonType)); 
} 

Pensando en cómo manejar un valor null de s, hay una tercera opción que nadie ha utilizado aún:

public static bool EqualsAny(this string s, IEnumerable<string> tokens, StringComparison comparisonType) 
{ 
    if (s== null) return tokens.Any(t => t == null); 
    return tokens.Any(t => s.Equals(t, comparisonType)); 
} 

Por último, en cuanto a su aplicación elegido: si va a tener sobrecargas, que también podría tener la sobr IEnumerable ds también, y haz que tu código params los llame.

+0

Estoy de acuerdo en que debe verificarse nulo, pero no estoy seguro de que deba siempre devuelve falso en una cadena vacía. –

+0

Sí, pensé en eso después de ver la publicación en la vista en vivo en lugar de una ventana de vista previa actualizada –

+0

if (cadena == nulo)? – Will

3

Otra opción sería. Esto simplificará su sitio de llamadas ya que si tiene un par de cadenas su correspondencia contra usted no tendrá que crear la matriz o lista en el código.

public static bool EqualsAny(this string s,StringComparison comparisonType, param string[] tokens) 
{ 
    return EqualsAny(s,comparisonType,tokens); 
}  

public static bool EqualsAny(this string s,StringComparison comparisonType, IEnumerable<string>tokens)  
{ 
    //Throw nullReference to keep the semantics aligned with calling an instance member 
    if (s==null) throw new NullReferenceException();  
    foreach (string token in tokens)   
    {    
     if (s.Equals(token, comparisonType))    
     {     
      return true;    
     }   
    }   
    return false;  

} 
0

No hay nada de malo en sí con lo que estás haciendo. Sin embargo, este tipo de funcionalidad ya existe en varias formas diferentes.

Ejemplo:

var candidates = List<SomeObject>(); 
if (candidates.Count(c=> string.Compare(c.PropertyValue, queryString["secure"], StringComparison.InvariantCultureIgnoreCase) == 0) > 0) 
{ 
parameters.Protocol = Protocol.https; 
} 
+0

Yeh, pero si lo haces mucho, entonces el método de extensión auxiliar proporciona un código mucho más legible, y eso en sí mismo tiene mucho valor. – joshcomley

Cuestiones relacionadas