2012-03-28 29 views
5

Tôi có nhiều đoạn mã cần chạy một lần trong khi khởi tạo.Làm cầu chì với boolean

tôi phải sử dụng một lá cờ boolean cách này bởi vì nó là trong một sự kiện

bool _fuse; 

void PerformLayout() 
{ 
    Size size; 

    if (!_fuse) 
    { 
     size = _InitialContainerSize; 
     _fuse = true; 
    } 
    else 
     size = parent.Size; 

    // ... 
} 

Bởi vì nó thường xảy ra, tôi đã làm một cái gì đó để làm cho biến boolean này trông giống như một cầu chì :

Vì vậy, tôi đã làm điều này:

bool _fuse; 

void PerformLayout() 
{ 
    Size size; 

    if (!Burnt(ref _fuse)) 
     size = _InitialContainerSize; 
    else 
     size = parent.Size; 

    // ... 
} 

Nếu nó được khởi tạo sai, kết quả của truy vấn trả về false một lần, làm cho switc h thành true và các cuộc gọi liên tiếp trả về true.

public static bool Burnt(ref bool value) 
{ 
    if (!value) 
    { 
     value = true; 
     return false; 
    } 
    else 
     return true; 
} 

Tất nhiên, nó hoạt động, nhưng tôi chỉ hài lòng vừa phải và tôi chắc chắn có nhiều giải pháp thanh lịch hơn. Điều gì sẽ là của bạn?

+2

'giá trị trả lại || ! (giá trị = true); '(chỉ đùa thôi!) –

+0

Thú vị. Cho đến nay tổng kiểm đếm là ba upvotes và ba phiếu để đóng. –

+0

Không phải là một câu hỏi thực sự. Nên ở trên trang web của người xem mã. Không phải ở đây. – leppie

Trả lời

1

Tôi nghĩ rằng Sức mạnh tổng hợp trong việc tránh sự lặp lại ở đây là đúng (ngay cả khi sự lặp lại là rất nhỏ ... nhưng vẫn). Chỉ cần đóng gói nó và đặt tên cho nó đúng cách:

struct InitializerGuard { 
    private bool hasRun; 

    public bool HasRun() { 
     if (hasRun) 
      return true; 
     hasRun = true; 
     return false; 
    } 
} 

Cách sử dụng:

InitializerGuard sizeInitializer; 

void PerformLayout() 
{ 
    Size size; 

    if (!sizeInitializer.HasRun()) 
     size = _InitialContainerSize; 
    else 
     size = parent.Size; 

    // ... 
} 

Nhưng nếu bạn thấy mình sử dụng mô hình này rất thường xuyên này có thể chỉ ra rằng một refactoring là theo thứ tự. Có lẽ chỉ cần gán giá trị mặc định cho một số biến? Tại sao họ không khởi tạo, dù sao?

+1

hoặc chỉ: 'Kích thước kích thước = HasRun()? parent.Size: _initSize; ' – leppie

+0

Đây là trang nhã và R CLE RÀNG. Tôi thích nó. Tôi nghĩ tôi sẽ sao chép cái này. (Tôi có thể thay đổi phương thức HasRun thành một thuộc tính thay thế?) - Tôi có thể refactor một phần mã của tôi tốt hơn, nhưng trong nhiều trường hợp tôi không có lựa chọn vì nó được sử dụng trong một số sự kiện. ngọn lửa đầu tiên. – Larry

+1

@Laurent Properties không được có tác dụng phụ. Ít nhất, điều này vít lên trình gỡ lỗi của bạn (nếu bạn gỡ lỗi mã của bạn và thêm một chiếc đồng hồ cho biến này, tài sản được đánh giá tại thời điểm tùy ý, do đó thay đổi hành vi của bạn). Vì vậy, nếu bạn làm cho một tài sản này, bạn phá vỡ mã của bạn theo cách "thú vị". ;-) –

1

Bạn có thể sử dụng các loại nullable và các nhà điều hành coalescing null để khai báo một tài sản Size:

Size? _containerSize; 

Size ContainerSize { 
    get { 
    return (_containerSize ?? (_containerSize = _InitialContainerSize)).Value; 
    } 
} 

Sau đó bạn có thể sử dụng nó như thế này:

void PerformLayout() { 
    var size = ContainerSize; 
    // ... 
} 

Nếu loại bạn muốn khởi tạo lười biếng là một kiểu tham chiếu nó trở nên đơn giản hơn.

Một tùy chọn khác là sử dụng loại Lazy<T>. Điều này có thể được sử dụng trong các trường hợp đa luồng nơi mã ở trên có thể bị hỏng:

Lazy<Size> _containerSize = new Lazy<Size>(() => _InitialContainerSize); 

void PerformLayout() { 
    var size = _containerSize.Value; 
    // ... 
} 
1

Có nhiều cách để đạt được điều này. Bạn có thể tạo một máy trạng thái phức tạp thực hiện logic của bạn (nhanh nhất) nhưng trong nhiều trường hợp, điều đó sẽ quá mức cần thiết. Ngoài ra, bạn có thể theo dõi một boolean giữ trạng thái của cá thể của bạn giống như bạn có bây giờ. Bạn cũng có thể quyết định kết hợp cả hai giải pháp vào một máy nhà nước đơn giản với các phương pháp tương tự (moderatly nhanh):

public class TestClass 
{ 
    private Action performLayoutAction; 

    public TestClass() 
    { 
     // initial state 
     performLayoutAction = InitializePeformLayout; 
    } 

    public void PerformLayout() 
    { 
     performLayoutAction(); 
    } 

    private void InitializePeformLayout() 
    { 
     // whatever 

     performLayoutAction = ContiniousPerformLayout; 
    } 

    private void ContiniousPerformLayout() 
    { 
     // whatever 
    } 
} 
Các vấn đề liên quan