2010-02-22 10 views
13

Đây chỉ là câu hỏi "Tôi tò mò".C# - Làm thế nào để tạo ra một vòng lặp vô hạn không thể phát hiện?

Trong C# -in-depth, Jon Skeet nói về biểu thức lambda:
"nếu có loại trả về không phải mọi đường dẫn mã phải trả về giá trị tương thích". (Trang 233)

Các chú thích sau đó nói:
"Mã đường ném ngoại lệ không cần phải trả lại một giá trị, tất nhiên, và không phải làm vòng lặp vô hạn phát hiện." (Trang 233)

Tôi tự hỏi điều gì cấu thành một vòng lặp vô hạn không thể phát hiện được?

Điều này có thể được thực hiện chỉ bằng logic không? hoặc nó được thực hiện bằng cách sử dụng các yếu tố bên ngoài như một cơ sở dữ liệu hoặc hệ thống tập tin?

+0

@JonSkeet có thể anh ấy có thể làm rõ. –

Trả lời

21

gì Jon là đề cập đến được mô tả trong phần 8.1 của đặc tả. Trình biên dịch chỉ có thể phát hiện các vòng vô hạn rất đơn giản, như:

while(true) { if (0 != 0) return 123; } 

Trình biên dịch đủ thông minh để thấy rằng không bao giờ đạt được và do đó vòng lặp chạy mãi mãi. Nó là hợp pháp, mặc dù điên, nói:

int M() { while(true) { } } 

vì dù không có con đường mà trả về một int, đó cũng là không có con đường mà trả mà không trả lại một int!

Trình biên dịch không đủ thông minh để tìm các loại vòng lặp vô hạn khác. Ví dụ:

int x = 123; 
while(true) { if (x * 0 != 0) break; } 

Đây rõ ràng là vòng lặp vô hạn. Nhưng trình biên dịch không biết điều đó. Trình biên dịch nói "tốt, có thể có một số giá trị của x trong đó x * 0 không phải là số không, vì vậy sau đó phá vỡ là có thể truy cập, vì vậy đây không phải là một vòng lặp vô hạn". Bạn và tôi biết rằng điều này là không thể bởi vì chúng ta biết toán học, nhưng trình biên dịch thì không.

Đọc phần 8.1 nếu bạn muốn biết chi tiết.

+3

Tôi thực sự không nhớ việc viết này - điều này gợi ý rằng chú thích là do ảnh hưởng của bạn :) –

+2

@Jon: Ban đầu bạn viết "Đường dẫn mã ném ngoại lệ không cần phải trả về giá trị, tất nhiên". Tôi lưu ý rằng các vòng vô hạn có thể phát hiện được tính là các điểm kết thúc không thể truy cập được. –

+2

Quyền - điều đó dường như có nhiều khả năng chi tiết hơn cho từng người trong chúng ta để tìm ra :) –

3

Nó khá tầm thường để tạo vòng lặp vô hạn bằng các nguồn bên ngoài hoặc thậm chí lạm dụng các công cụ như giao diện.

Ví dụ:

public interface INumbers 
    { 
     int GetNumber(int arg); 
    } 
    public class StaticNumber : INumbers 
    { 
     public int GetNumber(int arg) 
     { 
      return 1; 
     } 
    } 
    public void DoStuff(INumbers num) 
    { 
     int i = 42; 
     while ((i = num.GetNumber(i)) != 0) 
     { 
      ; 
     } 
    } 

và sau đó một đơn giản

Action action =() => DoStuff(new StaticNumber());