2009-05-22 1 views
6

Bởi vì đây là nỗ lực đầu tiên của tôi tại một phương pháp mở rộng mà dường như khá hữu ích với tôi, tôi chỉ muốn chắc chắn rằng tôi đang đi xuống con đường đúngPhương pháp mở rộng đầu tiên của tôi, nó có thể được viết tốt hơn không?

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

gọi bởi

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

EDIT: Một số gợi ý xuất sắc thông qua, chính xác loại điều tôi đang tìm kiếm. Cảm ơn

EDIT:

tôi đã quyết định về việc thực hiện sau

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

tôi ưa thích sử dụng params qua IEnumerable vì nó đơn giản hóa mã gọi

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

Một xa khóc trên trước đây

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

Cảm ơn bạn một lần nữa!

+0

Cá nhân, tôi nghĩ rằng bạn nên đặt một câu hỏi sơ bộ trước khi tự hỏi về cú pháp của phương pháp mở rộng của bạn: Bạn có thậm chí còn muốn phương pháp này. Đầu tiên, như những người khác đã đề cập, nó chỉ là một đảo ngược của tokens.Any(), và thứ hai, trong ví dụ sử dụng của bạn, bạn đã thực hiện một khái niệm đơn giản về "đây có phải là một giá trị thực" hay không dễ đọc và thay thế nó với một biểu thức phức tạp liên quan đến một phương thức mở rộng tùy chỉnh và một mảng on-the-fly. IMO, các bit nhỏ phức tạp không cần thiết này bổ sung. – tnyfst

Trả lời

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

Với thông số, trước tiên bạn không phải buộc chuỗi của bạn vào mảng.

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

LINQ-ified (JC + tôi) với một TNMT (tiêu chuẩn khuôn khổ):

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

Làm cho thông số tokens của bạn tổng quát hơn - tức là biến nó thành IEnumerable<string>.

Ngoài ra, một phương thức tương đương đã tồn tại kéo dài IEnumerable<>, ví dụ: Any:

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

Ngoài ra, Joel là tất nhiên đúng: bạn có thể muốn kiểm tra null giá trị trước khi thực hiện các hành động (mã hóa phòng thủ). Điều này không an toàn hơn nhưng nó làm cho lỗi dễ dàng hơn để bản địa hóa.

+0

@ Jelel: bạn nói đúng. Tôi đã nói nhiều hơn về * bất kỳ loại xử lý lỗi nào. Việc ném 'NullReferenceException' có thể phù hợp hơn. Như bạn đã nói: chúng tôi không biết hành vi nào được ưa thích ở đây. –

+0

Eh, ý tôi là 'ArgumentNullException'. –

+0

Tôi muốn nói rằng có, nó chắc chắn kém an toàn hơn, và có thể còn khó bản địa hóa hơn, vì mã có thể chạy với giả định không hợp lệ trong một thời gian dài trước khi lỗi hiển thị. Việc ném một ngoại lệ có thể thích hợp hơn, nhưng chúng ta không thể biết được hành vi nào mà OP cần khi viết mẫu. Vì vậy, tốt hơn hoặc tồi tệ hơn thiên vị là cung cấp mã mà chỉ cần chạy. –

1

để đơn giản hóa việc sử dụng của EqualsAny bạn có thể sử dụng varargs và chiến lược mặc định cho 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 
} 

gọi bởi

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

params phải là đối số cuối cùng. – Will

7

Có! Trước tiên, bạn cần phải kiểm tra s cho null. Ngoài ra, để cho nó chấp nhận bất kỳ IEnumerable<string> cho thẻ chứ không phải chỉ là một mảng, và sau đó sử dụng các toán LINQ khác để làm việc kiểm tra:

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

Suy nghĩ về làm thế nào để xử lý một giá trị null cho s, có một phần ba lựa chọn không ai được sử dụng nào:

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

Cuối cùng, về việc thực hiện lựa chọn của bạn: nếu bạn đang đi để có quá tải, bạn cũng có thể có overloa IEnumerable ds là tốt, và có mã số params của bạn.

+0

Tôi đồng ý rằng nó nên được kiểm tra cho null, nhưng tôi không chắc chắn rằng nó nên luôn luôn trả về false trên một chuỗi rỗng –

+0

Vâng, tôi nghĩ về điều đó sau khi tôi thấy bài đăng trong chế độ xem trực tiếp thay vì sau đó một cửa sổ xem trước- được cập nhật –

+0

if (string == null)? – Will

3

tùy chọn khác sẽ được. Điều này sẽ đơn giản hóa trang web cuộc gọi của bạn vì nếu bạn có một vài chuỗi phù hợp với bạn, bạn sẽ không phải tạo mảng hoặc danh sách trong mã.

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

Không có gì sai với những gì bạn đang làm. Tuy nhiên, loại chức năng này đã tồn tại trong một số thời trang khác nhau.

Ví dụ:

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

Yeh, nhưng nếu bạn đang làm nó rất nhiều thì phương pháp mở rộng của trình trợ giúp cung cấp mã dễ đọc hơn nhiều - và bản thân nó có rất nhiều giá trị. – joshcomley