2009-03-24 29 views
6

Tôi đã giúp một đồng nghiệp gỡ lỗi một số hành vi lạ trong mã của họ. Mẫu sau đây minh họa điều này:Tại sao khối cuối cùng của tôi không hoạt động trong C#?

static void Main(string[] args) 
{ 
    string answer = Sample(); 
    Console.WriteLine(answer); 
} 

public static string Sample() 
{ 
    string returnValue = "abc"; 

    try 
    { 
     return returnValue; 
    } 

    catch (Exception) 
    { 
     throw; 
    } 

    finally 
    { 
     returnValue = "def"; 
    } 
} 

Mẫu này trở lại là gì?

Bạn sẽ nghĩ rằng vì khối cuối cùng, nó trả về "def" nhưng trên thực tế, nó trả về "abc"? Tôi đã bước qua mã và xác nhận rằng khối cuối cùng là trong thực tế gọi.

Câu trả lời thực sự là bạn không nên viết mã như thế này ngay từ đầu nhưng tôi vẫn bối rối về hành vi.

Chỉnh sửa: Để làm rõ luồng dựa trên một số câu trả lời.

Khi bạn duyệt qua mã, cuối cùng được thực hiện trước khi trả lại.

Duplicate của:What really happens in a try { return x; } finally { x = null; } statement?

Trả lời

3

Có, khối cuối cùng chạy sau khi hàm trả về, nhưng điều này không quan trọng. Hãy nhớ rằng giá trị trả về được truyền theo giá trị, vì vậy một biến tạm thời mới được tạo cho nó ở thời gian trả về, do đó khối cuối cùng không làm gì để ảnh hưởng đến giá trị trả về thực tế.Nếu bạn muốn hỗ trợ các hành vi mong muốn bạn có thể sử dụng một tham số ra, như vậy:

static void Main(string[] args) 
{ 
    string answer; 
    Sample(out answer); 
    Console.WriteLine(answer); 
} 

public static void Sample(out string answer) 
{ 

    try 
    { 
     answer = "abc"; 
     return; 
    } 

    catch (Exception) 
    { 
     throw; 
    } 

    finally 
    { 
     answer = "def"; 
    } 
} 

Hoặc, bạn chỉ có thể di chuyển các câu lệnh return bên ngoài của khối try, như vậy:

static void Main(string[] args) 
{ 
    string answer = Sample(); 
    Console.WriteLine(answer); 
} 

public static string Sample() 
{ 
    string returnValue; 
    try 
    { 
     returnValue = "abc"; 
    } 

    catch (Exception) 
    { 
     throw; 
    } 

    finally 
    { 
     returnValue = "def"; 
    } 

    return returnValue; 
} 

Tuy nhiên, do khối cuối cùng sẽ luôn ghi đè giá trị trả về, đây là một thiết kế có vấn đề.

12

của bạn "cuối cùng" khối được gán một giá trị để returnValue và không thực sự trả về một giá trị. "Trở về" đã xảy ra trước khi khối cuối cùng thay đổi giá trị và do đó "abc" được trả về.

Trong khi mã gây nhầm lẫn như những gì bạn đã làm không có ý nghĩa, những gì nó đang làm là chính xác.

+0

điều này là sai..Nếu câu lệnh trả về nằm trong khối thử, khối cuối cùng, nếu có, sẽ được thực hiện trước khi điều khiển trả về phương thức gọi. – TStamper

+0

TStamper - giá trị trả về được đánh giá trong thử trong khi biến vẫn là "abc", sau đó cuối cùng thực hiện và thay đổi việc gán biến nhưng KHÔNG phải cái đã được lưu trữ để được trả về. – Chuck

+0

đúng, nhưng từ ngữ sai. Từ những gì anh ta nói mã không tiếp tục chạy trong hàm mẫu – TStamper

0

Tôi không có chuyên gia, nhưng tôi sẽ phải đoán rằng hàm này trả về và sau đó sau đó gọi. Kể từ khi return returnValue đã được thực hiện, nó không thực sự quan trọng giá trị returnValue mất trong khối cuối cùng. Loại hành vi này có ý nghĩa, bởi vì nó nghĩa vụ phải thực hiện toàn bộ khối thử trước khối cuối cùng và cách duy nhất nó có thể làm đó là nếu nó trả về từ hàm như được cho là.

3

Khối finally chạy hiệu quả sau tuyên bố return. Vì vậy, bạn đã trả về giá trị cũ của abc trước khi bạn đi vào khối cuối cùng của mình.

(điều này là không chính xác cách thức hoạt động dưới mui xe, nhưng nó đủ gần cho các điểm ở đây)

2

Tìm thấy this liên kết một số thời gian trước đây rằng thỏa thuận với câu hỏi này. Ông đi đến những rắc rối của việc hiển thị mã IL mà lái xe về nhà chính xác những gì đang xảy ra.

0

Nếu bạn thực sự tò mò về những gì đang diễn ra, bạn có thể tải xuống và cài đặt Reflector. Đó là một công cụ tuyệt vời để đưa vào 'túi o thủ thuật' của bạn. Nó sẽ cho bạn biết những gì đang xảy ra bên dưới mui xe.

0

Khi đoán tôi muốn nói rằng bạn đang xác định những gì sẽ được trả về (tham chiếu đến chuỗi "abc") tại điểm mà câu lệnh trả về là.

Vì vậy, thực tế là cuối cùng sau đó đặt tham chiếu đó tham chiếu đến một chuỗi khác không ảnh hưởng đến giá trị trả về.

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