Khi nào sử dụng [Pure] trên hàm tạo?


19

Tôi đang tìm hiểu về các hợp đồng mã trong .NET và tôi đang cố gắng hiểu ý tưởng của các nhà xây dựng thuần túy. Các tài liệu hợp đồng mã quy định:

Tất cả các phương thức được gọi trong hợp đồng phải thuần túy; nghĩa là, họ không được cập nhật bất kỳ trạng thái có sẵn nào. Một phương thức thuần túy được phép sửa đổi các đối tượng đã được tạo sau khi nhập vào phương thức thuần túy.

Và các PureAttributetài liệu nêu:

Chỉ ra rằng một loại hoặc phương thức là thuần túy, nghĩa là nó không thực hiện bất kỳ thay đổi trạng thái có thể nhìn thấy nào.

Tôi hiểu các câu lệnh này khi nói đến các phương thức, nhưng các hàm tạo thì sao? Giả sử bạn có một lớp học như thế này:

public class Foo
{
    public int Value { get; set; }

    public Foo(int value) {
        this.Value = value;
    }
}

Hàm tạo này rõ ràng không ảnh hưởng đến trạng thái của Foođối tượng mới , nhưng nó không có tác dụng phụ nào khác (ví dụ: nó không thao tác bất kỳ tham số nào hoặc gọi bất kỳ phương thức không thuần túy nào). Đây có phải là một ứng cử viên cho [Pure]hay không? Tầm quan trọng của việc đặt một [Pure]thuộc tính trên một hàm tạo và khi nào tôi nên làm điều này trong mã của riêng mình?

Câu trả lời:


14

Bạn trang trí một phương pháp với [Pure]:

  • Nếu phương pháp không có tác dụng phụ. Ví dụ: nếu phương thức truy cập cơ sở dữ liệu và sửa đổi nó hoặc kết quả của nó phụ thuộc vào cơ sở dữ liệu, thì nó không thuần túy.

  • nếu bạn muốn sử dụng nó trong các hợp đồng mã. Ví dụ: nếu phương thức này là thuần túy , nhưng bạn không có ý định sử dụng nó trong các hợp đồng mã, việc thêm [Pure]sẽ không có lợi ích và sẽ không làm cho mã của bạn nhanh hơn.

Theo như nó liên quan đến các nhà xây dựng, có vẻ như chúng được coi là thuần túy trong .NET và không cần một thuộc tính rõ ràng. Tôi đã xem xét một số hàm tạo trong nguồn .NET Framework, chẳng hạn như DateTime, và chúng không có [Pure]thuộc tính.

Tôi cho rằng điều này được thực hiện vì nhiều lý do:

  • Có thể quá không thực tế khi phải viết một hàm tạo không tham số với [Pure]thuộc tính chỉ để có thể sử dụng lớp / struct trong hợp đồng.

  • Một số, chẳng hạn như String, không có nhà xây dựng rõ ràng.

  • Các nhà xây dựng được đối xử đặc biệt ngay cả các hợp đồng mã bên ngoài; ví dụ, bạn sẽ không ném ngoại lệ vào chúng .

  • [Pure]chỉ là một quy ước ở đây để đơn giản hóa cuộc sống của bạn, nhưng không có kiểm tra tĩnh thực tế để đảm bảo rằng phương thức được trang trí với thuộc tính này là thuần túy. void DestroyDatabase()có thể được trang trí là thuần túy và các hợp đồng mã sẽ không nhận thấy điều gì sai.

    Hiện tại không có thành phần nào của Hợp đồng mã kiểm tra xem các phương thức được khai báo là thuần túy thực sự. Do đó, nếu một lập trình viên trang trí một phương thức bằng [Pure], thì nó chỉ được tin.

    Từ hợp đồng mã số 5: Độ tinh khiết của phương pháp

  • Bản thân .NET Framework chứa các hàm tạo không thuần túy. Ví dụ, List<T>(IEnumerable<T> collection)thực sự không tinh khiết nếu việc lặp qua bộ sưu tập có tác dụng phụ.

  • Hợp đồng hét được giữ đơn giản. Tôi có thể dễ dàng tưởng tượng một hợp đồng như vậy Contract.Requires(!string.IsNullOrEmpty(name)), vì vậy có những lý do chính đáng để tuyên bố tĩnh string.IsNullOrEmptythuần.

    Mặt khác, nếu bạn cần một StringBuilderchuỗi để xây dựng chuỗi, bạn sẽ kiểm tra một cái gì đó bằng cách gọi một phương thức cá thể của lớp doanh nghiệp của bạn, có lẽ bạn đang sử dụng sai các hợp đồng. Đó cũng StringBuilder.ToStringlà lý do tại sao không được đánh dấu là thuần túy, ngay cả khi nó có thể (phải không?)


Nhiều hợp đồng mã trên các loại hệ thống được người kiểm tra hợp đồng giả định, bao gồm " bất kỳ phương thức nào có tên đủ điều kiện bắt đầu bằng" System.Diagnostics.Contract.Contract "," System.String "," System.IO.Path "hoặc" System .Type " ". Thật không may, tôi không chắc chắn nếu nhìn vào các loại .NET là quá hữu ích khi nói đến hợp đồng mã.
pswg

3
Độ tinh khiết là một trong những điều mà tất cả các mã được gọi cũng phải là thuần túy hoặc người gọi không phải là "thuần túy". Tôi thấy khó tin rằng tất cả các nhà xây dựng được coi là thuần túy theo mặc định.
Frank Hileman

@FrankHileman: tôi cũng vậy. Tôi không có trình biên dịch C # ngay bây giờ, nhưng nó sẽ đủ để viết một lớp với hàm tạo và không có [Pure]thuộc tính và sử dụng nó ở một nơi khác trong hợp đồng để có câu trả lời dứt khoát.
Arseni Mourzenko

1

Đối tượng không thể được sử dụng cho đến khi nó được xây dựng trong trường hợp này. Do đó, các nhà xây dựng là tinh khiết. Nếu hàm tạo gọi mã khác hoặc gọi một đại biểu và mã khác đã sửa đổi thuộc tính có thể thay đổi, thì nó sẽ không thuần túy. Để an toàn hơn, tốt hơn là làm cho tài sản bất biến.


Vì vậy, một constructor thuần là một phương thức thuần túy được phép thay đổi trạng thái của lớp hiện tại, miễn là nó thỏa mãn các điều kiện khác của thuần túy? BTW, Thuộc tính có thể thay đổi vì tôi muốn nhấn mạnh rằng chính lớp này không thuần túy.
pswg

@pswg: Bạn đã tạo một câu hỏi thú vị mà có lẽ phải được trả lời bởi Microsoft. Giả sử hàm tạo đã gọi một phương thức sửa đổi thuộc tính có thể thay đổi; các nhà xây dựng vẫn còn tinh khiết? Tôi nghĩ về mặt kỹ thuật sẽ không như vậy, mặc dù việc sửa đổi là "vô hình" đối với người xem bên ngoài. Vì không có mã nào khác được gọi trong ví dụ ban đầu của bạn, nên nó phải hoàn toàn theo bất kỳ định nghĩa nào tôi có thể nghĩ ra.
Frank Hileman

@pswg: Ngoại trừ việc tập thuộc tính cũng là một cuộc gọi phương thức .. Tôi nghĩ bạn nên hỏi trên các diễn đàn MSDN.
Frank Hileman

Tôi đoán nếu ý tưởng trung tâm của độ tinh khiết là liệu phương thức đó có tạo ra bất kỳ thay đổi nào có thể quan sát được hay không , thì theo nghĩa đó, bất kể nó có gọi các phương thức không thuần túy hay không, miễn là những thay đổi không thể được quan sát bởi bất kỳ người gọi nào, nó vẫn sẽ là một phương pháp thuần túy
pswg

@pswg: Đó là định nghĩa trừu tượng. Nhưng nếu tôi đang viết một bộ phân tích cho những thứ này, có lẽ một cuộc gọi phương thức không thuần túy cũng sẽ được xem xét để làm cho người gọi không thuần túy. Chỉ để đơn giản thực hiện. Sau đó, câu hỏi là, một hàm tạo là một cuộc gọi phương thức bình thường, hoặc phân tích đi sâu đến mức nào.
Frank Hileman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.