Tôi đang cố gắng viết một phương pháp an toàn chỉ có thể được gọi một lần (mỗi trường hợp đối tượng). Một ngoại lệ nên được ném nếu nó đã được gọi trước đó.Làm thế nào để: Viết một phương pháp an toàn chỉ có thể được gọi một lần?
Tôi đã đưa ra hai giải pháp. Cả hai đều đúng không? Nếu không, có gì sai với họ?
Với
lock
:public void Foo() { lock (fooLock) { if (fooCalled) throw new InvalidOperationException(); fooCalled = true; } … } private object fooLock = new object(); private bool fooCalled;
Với
Interlocked.CompareExchange
:public void Foo() { if (Interlocked.CompareExchange(ref fooCalled, 1, 0) == 1) throw new InvalidOperationException(); … } private int fooCalled;
Nếu tôi không nhầm, giải pháp này có lợi thế là lock-free (dường như không có liên quan gì trong trường hợp của tôi) và điều đó đòi hỏi ít trường riêng hơn .
Tôi cũng mở cho các ý kiến hợp lý về giải pháp nào nên được ưu tiên và đề xuất thêm nếu có cách tốt hơn.
Trong sự tò mò: Khi bạn nói rằng nó "ít phức tạp", bạn dường như ám chỉ đến tất cả những gì đang diễn ra đằng sau người khiếm thị; bạn sẽ đánh giá khả năng đọc/dễ hiểu về cấu trúc 'Interlocked.ExchangeCompare' cho một lập trình viên trung bình như thế nào? – stakx
@stakx: đó là ý kiến dành cho. Khi một lập trình viên gặp một cái gì đó họ không hiểu, họ nên tìm kiếm nó để họ hiểu nó. Đó là cách họ trở thành một lập trình viên tốt hơn. – thecoop
@thecoop Tôi không đồng ý, có đó là giải pháp chính xác nhất, nhưng nó không đơn giản, bạn cần biết về các hoạt động nguyên tử ... Đây là một quá trình khởi tạo và tôi khuyên bạn nên làm theo các mẫu khởi tạo được sử dụng rộng rãi (ví dụ: kiểm tra khóa). Ngoài ra các mẫu này ngăn bạn thiếu một cái gì đó mà có thể dễ dàng xảy ra khi làm luồng. – ntziolis