2010-07-24 34 views
6

Tôi muốn hạn chế giá trị của tham số số trong một hàm tạo trong phạm vi nhất định.Giới hạn giá trị của tham số trong một hàm tạo AT THIẾT KẾ THỜI GIAN

Tôi biết các cách thông thường là để làm một cái gì đó như sau:

public class Foo 
{ 
    public int MaxAmount { get; } 
    public int Amount { get; set; } 

    public Foo(int amount) 
    { 
     if (amount > MaxAmount) { Amount = MaxAmount; } 
     else if (amount < 1) { Amount = 1; } 
     else { Amount = amount; } 
    } 
} 

Nhưng những gì tôi không thích về việc này là người gọi không biết khi nào tài sản được thiết lập để một cái gì đó khác hơn những gì đã được chỉ định. Tôi có thể trả lại một ngoại lệ thay vì âm thầm kẹp giá trị, nhưng đó không phải là rất thân thiện.

Những gì tôi muốn là một cái gì đó tương tự như thế này:

public Foo(int(1, this.MaxAmount) amount) // Where int(minimumValue, maximumValue) 
{ 
    Amount = amount; 
}

trong đó người ta sẽ thậm chí không có khả năng nhanh chóng Foo với một giá trị không thể chấp nhận - khuôn khổ sẽ ngăn chặn nó.

Có điều gì giống như vậy không?

EDIT cho rõ ràng:

Những gì tôi đang theo đuổi là một phương tiện mà các tham số tự có thể mang và truyền đạt thông tin về những hạn chế của nó - trong một 'nướng trong' thời trang mà có thể, ví dụ, bề mặt trong Intellisense khi bạn viết cuộc gọi. Vì vậy, tôi muốn tránh các công việc của thậm chí cố gắng để nhanh chóng lớp nếu các giá trị cho các tham số không hợp lệ.

Nếu, ví dụ, chương trình đang chạy và người dùng nhập số (N) và nhấn nút tạo Foo mới với số lượng N bất hợp pháp, bây giờ tôi có ngoại lệ để xử lý và một cái gì đó để gỡ lỗi và sửa chữa. Tại sao thậm chí cho phép nó ở nơi đầu tiên? Nếu Foo được định nghĩa rõ ràng là có đường biên trên của thuộc tính Số lượng, thì điểm cho phép nhà phát triển viết Foo (5) khi tôi có thể thông báo cho anh ta rằng giá trị anh ta chuyển không hợp lệ vào thời điểm anh ta viết nó?

Nếu có một số cú pháp đường, như ParameterConstraint hoặc một cái gì đó, được xử lý bởi khung cho tôi để tôi không phải cuộn của riêng tôi vào mỗi lớp tôi viết, tôi nghĩ rằng sẽ rất hữu ích.

Trả lời

7

Bạn có thể thực hiện việc này bằng cách sử dụng kiểm tra hợp đồng tĩnh với Code Contracts (Chỉ cao cấp - Phiên bản chuẩn chỉ cung cấp kiểm tra hợp đồng thời gian chạy).

Cú pháp là đơn giản

public Foo(int amount) { 
    Contract.Requires(amount < MaxAmount); 
    ... 
} 

(Yêu cầu) hợp đồng được đánh giá bằng cách kiểm tra rằng các đối số bị hạn chế khi gọi phương pháp này. Trong trường hợp của bạn, sẽ rất khó để đánh giá đối số hàm tạo đối với trường dụ MaxAmount, vì bạn không thể kiểm tra giá trị đó trước đó. (Làm cho MaxValue tĩnh để giải quyết điều này).

Ví dụ về cuộc gọi như vậy.

int val = _getFromSomewhere(); 
var foo = new Foo(val); 
//This May produce compile time error 
// because the contract checker cannot prove you contract is met. 

Sửa chữa sẽ đảm bảo bạn đặt ràng buộc nơi bạn gọi được thực hiện.

int val = _getFromSomewhere(); 
if (val < Foo.MaxAmount) 
    var foo = new Foo(val); 
    //Will always compile fine, because contract is met. 

Khi bạn cài đặt Hợp đồng, trình kiểm tra tĩnh không được bật theo mặc định. Các thuộc tính dự án của bạn sẽ có một tab phụ để bạn có thể cấu hình các tùy chọn hợp đồng và cho phép kiểm tra tĩnh.

+1

Lưu ý rằng việc sử dụng 'Contract.Requires' là không đủ. Bạn vẫn cần một 'if (...) ném mới ArgumentOutOfRangeException()'. –

9

Tôi có thể trả lại ngoại lệ thay vì âm thầm kẹp giá trị, nhưng điều đó không thân thiện lắm.

Hãy nói gì? Ý bạn là gì, "thân thiện"? Người gọi không phải là bạn của bạn, đó là một đoạn mã khác đang cố gắng đặt giá trị ngoài phạm vi. Nhà phát triển đã viết mã nên được thông báo ngay lập tức rằng anh ấy đang làm điều gì đó sai.

Ném ngoại lệ!

+1

Tôi muốn * thông báo cho * người gọi rằng giá trị không hợp lệ, nhưng không thực hiện công việc cố gắng khởi tạo lớp. Tôi nghĩ sẽ rất tuyệt khi có phản ứng Intellisense rằng nó không hợp lệ, cho một. –

1

Hoặc ném ngoại lệ hoặc cung cấp một thuộc tính tĩnh để xác nhận số lượng

public static bool ValidateAmount(int amount) 
{ 
    if(amount > MaxAmount) 
     return false; 
    return true; 
} 
2

Bạn sẽ cần phải quấn các tham số lên trong một loại mới sau đó. ints biết số tiền tối đa của họ là gì và đó là int.MaxValue. Nếu đúng là trường hợp tham số tự biết số tiền tối đa của nó, và rằng nó không phải là một cái gì đó cụ thể cho lớp Foo, thì bạn sẽ cần tạo một kiểu khác để kiểm tra số tiền được chuyển vào nó. Khi nó đứng, chữ ký của hàm tạo của Foo chấp nhận bất kỳ cấu trúc dữ liệu int nào.

1

Không chắc chắn nếu điều này làm việc cho các loại thuộc tính trong C#, nhưng bạn có thể xác định một liệt kê chứa tất cả các giá trị chấp nhận được và sau đó đặt kiểu dữ liệu của thuộc tính đó. Điều đó sẽ buộc người gọi sử dụng điều tra và do đó biết giá trị nào được chấp nhận. Tất nhiên, nếu bạn có rất nhiều giá trị trong phạm vi chấp nhận được, thì việc liệt kê sẽ khó sử dụng.

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