2009-05-22 6 views
6

Ponieważ jest to moja pierwsza próba metodę rozszerzenia, które wydaje się dość użyteczne dla mnie, po prostu chcę się upewnić, jadę w dół właściwą drogęMoja pierwsza metoda rozszerzenia, czy można ją napisać lepiej?

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; 
    } 

nazywany przez

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

EDYTOWANIE: Kilka doskonałych sugestii, dokładnie tego rodzaju rzeczy, których szukałem. Dzięki

EDIT:

zdecydowałem na poniższym realizacji

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); 
} 

wolałem użyciu params nad IEnumerable ponieważ uproszczony kod wywołujący

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

daleko na poprzedni

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

Jeszcze raz dziękuję!

+0

Osobiście uważam, że należy zadać pytanie wstępne przed zastanawiać składni metodę rozszerzenia: czy nawet chcą tej metody. Po pierwsze, jak wspominali inni, jest to po prostu odwrócenie tokenów. Any(), a po drugie, w swoim przykładzie użycia, podjąłeś prostą koncepcję "jest to prawdziwa wartość", która powinna być łatwa do odczytania i zastąpienia to ze złożonym wyrażeniem obejmującym niestandardową metodę rozszerzenia i tablicę "w locie". IMO, te małe kawałki zbędnej złożoności sumują się. – tnyfst

Odpowiedz

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; 
} 

Dzięki paramom nie trzeba najpierw wciskać łańcuchów w tablicę.

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

Linq ified (JC + ja) z NRE (standard ramowej):

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

Ulepsz swój parametr tokens - tzn. Spraw, aby był to IEnumerable<string>.

Ponadto istnieje już równoważna metoda, która rozszerza się o IEnumerable<>, np. Any:

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

Również Joel jest odpowiedni kurs: może chcesz sprawdzić null wartości przed wykonaniem czynności (kodowanie obronny). Nie jest to bezpieczniejsze, ale ułatwia zlokalizowanie błędu.

+0

@Joel: masz rację. Mówiłem bardziej ogólnie o * każdym * rodzaju obsługi błędów. Rzucanie 'NullReferenceException' może być bardziej odpowiednie. Jak powiedziałeś: nie wiemy, które zachowanie jest tutaj preferowane. –

+0

Eh, miałem na myśli 'ArgumentNullException'. –

+0

Powiedziałbym, że tak, to zdecydowanie mniej bezpieczne i prawdopodobnie jeszcze trudniejsze do zlokalizowania, ponieważ kod mógł działać z nieprawidłowym błędnym założeniem przez długi czas, zanim błąd pojawi się w widoczny sposób. Rzucanie wyjątku może być bardziej odpowiednie, ale nie wiemy, jakie zachowanie potrzebuje OP przy pisaniu próbki. Tak więc dla lepszego lub gorszego nastawienia jest dostarczenie kodu, który po prostu działa. –

1

aby uprościć korzystanie z EqualsAny można użyć varargs i domyślną strategię 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 
} 

Wywoływana przez

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

params musi być ostatnim argumentem – Will

7

Tak! Najpierw musisz sprawdzić s dla wartości null. Ponadto, niech ponosi IEnumerable<string> dla tokenów raczej niż tylko tablicę, a następnie użyć innych operatorów LINQ to zrobić należy sprawdzić:

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)); 
} 

myśleć o tym jak radzić sobie null wartości dla S, tam trzeci opcja nikt dotychczas stosowane:

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)); 
} 

Wreszcie, w odniesieniu do wybranego realizacji: jeśli masz zamiar mieć przeciążeń, równie dobrze można mieć IEnumerable overloa ds również, i mieć swój kod params te.

+0

Zgadzam się, że powinien on zostać sprawdzony pod kątem zerowej wartości, ale nie jestem pewien, czy powinien zawsze zwracam wartość false w pustym ciągu znaków –

+0

Tak, pomyślałem o tym po tym, jak zobaczyłem wpis w widoku na żywo zamiast okna podglądu - zaktualizowano –

+0

if (string == null)? – Will

3

Innym rozwiązaniem byłoby. Uprości to twoją stronę wywoławczą, ponieważ jeśli masz kilka ciągów, twoje dopasowanie przeciwko tobie nie będzie musiało tworzyć tablicy ani listy w kodzie.

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

Nie ma nic złego w tym, co robisz. Jednak ten typ funkcjonalności już istnieje w kilku różnych modach.

Przykład:

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

Yeh, ale jeśli robisz to dużo, to metoda rozszerzenia pomocnika zapewnia znacznie bardziej czytelny kod - a to samo w sobie ma dużą wartość. – joshcomley

Powiązane problemy