2013-05-16 28 views
5

Tôi có một phương thức mở rộng đơn giản cho lớp chuỗi sẽ loại bỏ tất cả các ký tự không phải số từ một chuỗi. Vì vậy, nếu tôi có một chuỗi như ví dụ như một số điện thoại như "(555) 215-4444" nó sẽ chuyển đổi nó thành "5552154444". Có vẻ như sau:Xử lý null theo phương pháp mở rộng

public static string ToDigitsOnly(this string input) 
{ 
    Regex digitsOnly = new Regex(@"[^\d]"); 
    return digitsOnly.Replace(input, String.Empty); 
} 

Tôi chỉ tự hỏi cách thanh lịch nhất để xử lý giá trị null ở đây là gì? Có một mô hình điển hình để làm theo trong những trường hợp này, chẳng hạn như trở lại một giá trị null nếu một null được thông qua trong? Có vẻ như kể từ khi tôi đang mở rộng lớp chuỗi ở đây tôi có thể muốn cho phép các giá trị null và không ném một ngoại lệ tranh luận (vì tôi không thực sự vượt qua trong một cuộc tranh luận khi tôi sử dụng này ...)? Nhưng một số người có thể lập luận rằng tôi nên ném một ngoại lệ như một phương pháp 'bình thường'. Thực hành tốt nhất bạn đang sử dụng ở đây là gì?

Cảm ơn!

+1

tôi sẽ đối xử với phương pháp mở rộng như một cái bình thường. Nó chỉ là một cách để dọn dẹp cách mọi người đọc mã. Thay vì StringFunctions.ToDigitsOnly (s) bạn rút ngắn nó để s.ToDigitsOnly(), vì vậy nếu bạn muốn ném một ngoại lệ trong một, ném nó trong khác. –

+1

Nếu null là giá trị hợp lệ/được mong đợi trong ứng dụng của bạn, hãy trả về giá trị rỗng. Nếu không, hãy ném một ngoại lệ. Cá nhân tôi sẽ ném một ArgumentException ở đây. – JosephHirn

+2

Là một lưu ý phụ; bạn không cần một Regex ở đây 'String.Join (" ", input.Where (char.IsDigit))' – I4V

Trả lời

9

Bạn có thể làm theo các nguyên tắc nhất ngạc nhiên: mô hình sử dụng thực hiện trong LINQ:

public static string ToDigitsOnly(this string input) 
{ 
    if(input == null) 
      throw new ArgumentNullException("input"); 

    Regex digitsOnly = new Regex(@"[^\d]"); 
    return digitsOnly.Replace(input, String.Empty); 
} 

Bạn có thể sử dụng phương pháp, proposed by Jon Skeet. Nó sẽ làm giảm séc của bạn đơn giản chỉ để

input.ThrowIfNull("input"); 

Cũng Jon có một phần tốt 10.2.4 Gọi một phương thức trên một tham chiếu null trong C# in x, quote:

KIỂM TRA CHO ĐÌNH CHỈ Là một nhà phát triển tận tâm, tôi chắc chắn rằng các phương pháp sản xuất của bạn luôn kiểm tra tính hợp lệ của các đối số trước khi tiến hành . Một câu hỏi tự nhiên phát sinh từ tính năng kỳ quặc của phương pháp mở rộng này là ngoại lệ để ném khi đối số đầu tiên là null (giả sử nó không có nghĩa là). Nếu nó là ArgumentNullException, như thể nó là một đối số bình thường, hoặc nó có phải là là NullReferenceException, đó là điều gì sẽ xảy ra nếu phương pháp mở rộng là phương pháp bắt đầu? Tôi đề xuất tên cũ: nó vẫn là một đối số, ngay cả khi cú pháp phương pháp mở rộng không làm rõ điều đó.

Tôi thấy khuyến nghị này là (và từ kinh nghiệm cá nhân của tôi): tốt hơn là kiểm tra null, đặc biệt cho phương pháp tĩnh và không dựa vào giá trị null. Chỉ một ngoại lệ nếu đó là mục đích chính xác của phương pháp của bạn, ví dụ: ThrowIfNull hoặc IsNullOrEmpty phương pháp mở rộng.

+0

Các phương thức LINQ hầu như không bao giờ có bất kỳ đầu ra nào mà chúng có thể cung cấp một cách hợp lý khi chúng có các tham số null. Đó không phải là trường hợp ở đây, vì vậy nó không phải là một sự so sánh công bằng. – Servy

+0

@Servy xin lỗi, không muốn tranh luận, nhưng tại sao vậy? Sự khác nhau trong 'myString.Where (char.IsDigit)' và 'myString.ToDigitsOnly()' là gì? –

1

Nó không thực sự quan trọng miễn là bạn giao tiếp tốt với hành vi (để người dùng cuối biết điều gì sẽ xảy ra).

Cân nhắc sử dụng tích hợp sẵn XML Documentation Comments để truyền đạt hành vi mong đợi.

/// <exception cref="ArgumentNullException">argument is null.</exception> 
public string Example(string argument) 
{ 
    if (argument == null) 
     throw new ArgumentNullException(); 
    return argument.ToString(); 
} 
tài liệu

Xem MSDN cho nhiều ví dụ:

1

Giả sử tôi có điều này:

class A 
{ 
    public void F() 
    { 
     //do stuff 
    } 
} 

Nếu tôi sau đó chạy đoạn mã sau, điều gì xảy ra?

A a = null; 
a.F(); 

Bạn nhận được NullReferenceException. Vì vậy, tôi sẽ nói cách thích hợp để viết một phương pháp mở rộng tương đương sẽ như sau.

class A 
{ 
} 

static class AExtensions 
{ 
    void F(this A a) 
    { 
     if (a == null) 
     { 
      throw new NullReferenceException(); 
     } 
     //do stuff 
    } 
} 

Tuy nhiên, .NET không đồng ý với tôi về điều này. Các tiêu chuẩn trong .NET là thay vì ném một ArgumentException - vì vậy nó có lẽ tốt nhất để làm điều đó thay thế.

+0

Tôi sẽ không đề nghị điều đó. Bạn có thể gọi phương thức đó với 'AExtensions.F (null)'. Người ta sẽ mong đợi 'ArgumentNullException' khi một tham số' null' được thông qua. –

+1

@JimMischel True. Tôi có xu hướng 99% thời gian xử lý các phương pháp mở rộng như thể họ là thành viên của loại họ đang áp dụng cho, mặc dù. Trường hợp bạn gọi chúng như một phương pháp tĩnh là không bình thường mặc dù hợp lệ. Có thực sự không có gì sai với việc sử dụng ArgumentException mặc dù. Tôi đoán nếu NET đang làm nó đó là con đường để đi. –

+0

Các vấn đề khác với ném 'NullReferenceException' là nó không thực sự giao tiếp những gì nguồn gốc của lỗi là. Lỗi thực sự là tại trang cuộc gọi, trong đó một tham số null được thông qua. Nếu mã của bạn ném NRE (mà nó sẽ làm anyway, nếu bạn chỉ cố gắng để truy cập nó), khách hàng được dẫn đến tin rằng lỗi là trong phương pháp mở rộng. Điều này đặc biệt đúng nếu khách hàng đang sử dụng một thư viện mà anh ta không có nguồn. 'ArgumentNullException' cho client biết chính xác * vấn đề là gì. –

1

Đơn giản; Tạo một phương thức khác cho String, giả sử IsInValid()

công thức tĩnh bool IsInValid (chuỗi này) { return (s == null) || (s.Length == 0); }

sử dụng bất cứ nơi nào bạn muốn kiểm tra ...

Hơn nữa, bạn có thể sử dụng phần mở rộng này bất cứ nơi nào

Các vấn đề liên quan