2009-04-30 27 views
7

Trong một số mã Delphi 7 Tôi đang duy trì, tôi đã nhận thấy rất nhiều trường hợp các nội dung sau:Trong delphi 7, là `try ... trừ nâng cao; kết thúc, `có ý nghĩa gì cả?

with ADOQuery1 do begin 
    // .. fill out sql.text, etc 
    try 
    execSQL; 
    except 
    raise; 
    end; 
end; 

Dường như với tôi rằng những thử khối có thể được gỡ bỏ, vì họ không làm gì cả. Tuy nhiên, tôi cảnh giác với các tác dụng phụ tinh tế có thể ..

Có ai nghĩ đến bất kỳ trường hợp nào trong đó các khối này thực sự có thể làm bất cứ điều gì không xảy ra nếu không có chúng không?

+0

Xem thêm: http: // stackoverflow.com/questions/717489/the-difference-giữa-re-throwing-parameterless-catch-and-not-do-bất cứ điều gì –

Trả lời

10

Trong ngữ cảnh này, thao tác nâng cao không có hiệu lực và cần được loại bỏ vì đơn giản chỉ cần tăng lại ngoại lệ là khối ngoại lệ vừa mới bắt. nâng cao thường được sử dụng để chuyển điều khiển đến cuối khối khi không có xử lý lỗi thích hợp có sẵn. Trong trường hợp sau, chúng tôi xử lý ngoại lệ tùy chỉnh, nhưng bất kỳ ngoại lệ nào khác đều phải được xử lý ở nơi khác.

try 
    someOperation; 
except 
    on e: ECustomException do 
    SomeCustomHandelr; 
    else 
    begin 
     // the raise is only useful to rethrow the exception to an encompasing 
     // handler. In this case after I have called my logger code. as Rob 
     // mentioned this can be omitted if you arent handling anything because 
     // the compiler will simply jump you to the next block if there is no 
     // else. 
     LogUnexpectedException('some operation failed',e); 
     raise; 
    end; 
end; 

Hãy cẩn thận khi có hình thức tương tự mà không "tăng" mà KHÔNG có tác dụng phụ khi ăn/giấu bất kỳ ngoại lệ nào. thực hành bởi các nhà phát triển rất vô đạo đức, những người đã hy vọng chuyển sang vị trí với cuộc thi.

with ADOQuery1 do begin 
    // .. fill out sql.text, etc 
    try  
    execSQL; 
    except 
    // no handler so this just eats any "errors"  
    end; 
+0

Vâng, tôi đã thấy rằng một trong codebase này: \ – Blorgbeard

+2

Mike, ví dụ đầu tiên của bạn KHÔNG yêu cầu "nâng cao". Bất kỳ ngoại lệ nào không thuộc loại ECustomException sẽ tự động truyền cho trình xử lý tiếp theo. Chỉ cần bỏ qua toàn bộ phần "khác". –

+0

Bạn chính xác. nó có thói quen. thời gian duy nhất nâng cao khác là cần thiết là nếu yo có một số mã khác mà bạn muốn thực thi và sau đó nó cần thiết. bị gỉ trong tuổi già của tôi. – MikeJ

6

Xóa mã ngoại trừ trong đoạn mã trên sẽ không có sự khác biệt. Bạn có thể (và tôi tin rằng bạn nên vì nó đang giảm khả năng đọc) loại bỏ nó.

+0

Tôi chắc chắn đồng ý về khả năng đọc – Blorgbeard

+0

Một lý do khác để thả mã như thế này: khi gỡ lỗi, bạn don ' Tôi không cần phải bước qua tất cả các trường hợp này trong trường hợp ngoại lệ. –

2

OK, thực sự có hai câu hỏi tại đây.

Đầu tiên, nó có ý nghĩa: nếu execSQL ném ngoại lệ, nó bị chặn bởi khối thử và được chuyển tiếp đến ngoại trừ. Sau đó, nó được chuyển tiếp bằng cách nâng lên khối cao hơn tiếp theo.

Thứ hai, là hữu ích? Chắc là không. Nó gần như chắc chắn là kết quả của một trong ba điều sau:

  1. Một người có mái tóc nhọn viết một khối thử. "
  2. Một người nào đó có nghĩa là quay lại và biến các ngoại lệ được thực hiện bởi số execSQL thành một số ngoại lệ khác, có ý nghĩa hơn.
  3. Một người nào đó mới không biết rằng những gì họ viết là đẳng cấu để cho phép môi trường dễ chịu hơn lo lắng về ngoại lệ, và vì vậy nghĩ rằng họ phải chuyển tiếp nó.
+0

Điều làm tôi lo lắng là tôi biết ai đã viết mã này, và tôi không nghĩ rằng 1-3 áp dụng ở đây. Ngoại trừ có thể 3 .. Hmm. – Blorgbeard

+0

Ồ, anh ta đã rời đi nên tôi không thể hỏi anh ta. – Blorgbeard

+0

Mã người trong Java có trước đây không? Có lẽ sau đó anh ta nghĩ rằng các ngoại lệ phải bị bắt và không thử khác. –

2

tôi có thể trả lời một chút nhanh, xem ở cuối ...
Giống như nó là, nó là vô ích cho việc áp dụng.
Thời gian!

Hiện tại ở bên "lý do".Nó có thể là để chuẩn hóa các trường hợp ngoại lệ xử lý nếu có/được/sẽ/đang ở những nơi khác/một số loại mã khai thác gỗ chèn vào trước tăng:

try 
    execSQL; 
    except 
    // Log Exception.. 
    on E: Exception do 
    begin 
     LogTrace(Format('%s: Exception Message[%s]',[methodname, E.Message])); 
     raise; 
    end; 
    end; 

hoặc mã Cleanup:

try 
    execSQL; 
    except 
    //some FreeAndNil.. 
    raise; 
    end; 

Cập nhật: Sẽ có 1 trường hợp mà tôi sẽ thấy một số việc sử dụng giống như ...
... để có thể đặt điểm ngắt trên đường dây raise, để có cơ hội xem điều gì đang xảy ra trong ngữ cảnh trên khối mã đó.

+2

Điều thứ hai hoàn toàn không đơn điệu, người ta sẽ sử dụng cuối cùng thay thế. Những thứ như thế này thực sự làm giảm khả năng đọc của cơ sở mã, vì vậy đó cũng là lý do để sửa nó. – mghie

+2

thay thế FreeAndNil bằng Connection.Rollback – Blorgbeard

+0

Chính xác Blorgbeard, bất kỳ loại dịch vụ vệ sinh nào cần được thực hiện CHỈ nếu mọi thứ xảy ra sai, và sau đó bạn chuyển sang với Ngoại lệ sủi bọt lên –

1

Thực ra, tôi nên gửi này như bình luận cho câu trả lời của François, nhưng tôi không biết là nó có thể chèn mã định dạng có :(Vì vậy, tôi gửi bài này là câu trả lời

2mghie:.

Điều thứ hai là hoàn toàn unidiomatic, người ta sẽ sử dụng cuối cùng để thay thế.

Không, "cuối cùng" sẽ làm sạch đối tượng luôn. "Ngoại trừ" - chỉ ngoại lệ. Hãy xem xét trường hợp của hàm, tạo ra, điền và trả về một đối tượng:

function CreateObj: TSomeObj; 
begin 
    Result := TSomeObj.Create; 
    try 
    ... // do something with Result: load data, fill props, etc. 
    except 
    FreeAndNil(Result); // oops: bad things happened. Free object to avoid leak. 
    raise; 
    end; 
end; 

Nếu bạn đặt "cuối cùng" ở đó - chức năng sẽ trở lại không luôn. Nếu bạn bỏ qua "thử" khối ở tất cả - sẽ có tài nguyên bị rò rỉ trong trường hợp ngoại lệ trong "...".

P.S. Tất nhiên, bạn có thể sử dụng "cuối cùng" và kiểm tra exceptObj, nhưng ... không phải là xấu xí?

+0

Tôi đồng ý, xem nhận xét của tôi về câu trả lời của Francois. – mghie

2

Mã này không có gì khác ngoài việc cho phép lập trình viên ban đầu đặt điểm ngắt trên 'Tăng lên' và để xem ngoại lệ gần hơn trong nguồn đến nguyên nhân có thể của nó. Theo nghĩa đó, nó là một kỹ thuật gỡ lỗi hoàn toàn hợp lý.

0

Tiêu đề chứa câu hỏi khá rộng, trong khi giải thích của nó đưa ra một ví dụ cụ thể hơn. Vì vậy, tôi trả lời cho câu hỏi như thế nào nó tiến hành từ ví dụ, có thể nghi ngờ thêm bất cứ điều gì hữu ích cho những gì đã được nói ở đây.

Nhưng, có lẽ Blorgbeard thực sự muốn biết cho dù đó là ở tất cả có ý nghĩa để try ... except raise; end. Trong Delphi 7, nếu tôi nhớ lại chính xác, Exit sẽ kích hoạt phần finally của khối try-finally (như thể nó là một loại ngoại lệ nào đó). Ai đó có thể xem xét hành vi như vậy không phù hợp với nhiệm vụ của họ và việc sử dụng công trình được đề cập là một cách giải quyết. Chỉ

nó vẫn sẽ là xa lạ đối với sử dụng một đơn raise; ở đó, nhưng sau đó chúng ta nên đã nói về tính hữu dụng hơn ý nghĩa, như Charlie đã gọn gàng quan sát.

+0

Cuối cùng các khối thực hiện trong * tất cả * các trường hợp, ngoại lệ hay không, do đó không thể thực hiện được. – Blorgbeard

0

Mã này không làm gì ngoại trừ việc tăng lại một ngoại lệ mà tất cả sẽ được nâng lên mà không cần thử, ngoại trừ khối. Bạn có thể loại bỏ nó một cách an toàn.

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