Мой первый метод расширения, это может быть написано лучше? - PullRequest
6 голосов
/ 22 мая 2009

Поскольку это моя первая попытка использования метода расширения, который кажется мне весьма полезным, я просто хочу убедиться, что иду по правильному маршруту

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

Вызывается

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

РЕДАКТИРОВАТЬ: Некоторые отличные предложения приходят именно то, что я искал. Спасибо

EDIT:

Я выбрал следующую реализацию

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

Я предпочел использовать params вместо IEnumerable, потому что это упростило код вызова

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

Далеко от предыдущего

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

Еще раз спасибо!

Ответы [ 6 ]

7 голосов
/ 22 мая 2009

Да! Во-первых, вам нужно проверить s на ноль. Кроме того, пусть он принимает любые IEnumerable<string> для токенов, а не только массив, а затем использует другие операторы linq для проверки:

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

Думая о том, как обработать значение null для s, есть третий вариант, который еще никто не использовал:

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

Наконец, относительно выбранной вами реализации: если вы собираетесь иметь перегрузки, вы также можете иметь перегрузки IEnumerable, и ваш код params должен вызывать их.

5 голосов
/ 22 мая 2009
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;
}

При использовании params вам не нужно сначала вводить строки в массив.

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

Linq-ified (JC + me) с 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));
}
3 голосов
/ 22 мая 2009

Другой вариант будет. Это упростит ваш сайт вызовов, так как если у вас есть пара строк, с которыми вы будете сопоставлять, вам не придется создавать массив или список в коде.

 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;    

}
2 голосов
/ 22 мая 2009

Сделайте ваш параметр tokens более общим - то есть сделайте его IEnumerable<string>.

Также уже существует эквивалентный метод, который расширяет IEnumerable<>, например, Any

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

Кроме того, Джоэл, конечно, прав: вы можете проверить значения null перед выполнением действий (защитное кодирование). Это не является более безопасным, но облегчает локализацию ошибки.

1 голос
/ 22 мая 2009

, чтобы упростить использование EqualsAny, вы можете использовать varargs и стратегию по умолчанию для 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
}

Вызывается

if (queryString["secure"].EqualsAny("true", "1")) {
    parameters.Protocol = Protocol.https;
}
0 голосов
/ 22 мая 2009

Нет ничего плохого в том, что вы делаете. Однако этот тип функциональности уже существует в нескольких модах.

Пример:

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