2009-09-16 36 views
8

Cả trong SQL và C#, tôi chưa bao giờ thực sự thích tham số đầu ra. Tôi không bao giờ được thông qua ByRef tham số trong VB6, một trong hai. Một cái gì đó về đếm trên các tác dụng phụ để có được một cái gì đó thực hiện chỉ làm phiền tôi.Có gì sai với thông số đầu ra?

Tôi biết chúng là một cách để không thể trả về nhiều kết quả từ một hàm, nhưng một rowset trong SQL hoặc một kiểu dữ liệu phức tạp trong C# và VB cũng hoạt động tốt và dường như tự tài liệu hơn.

Có điều gì sai trái với suy nghĩ của tôi, hoặc có nguồn lực từ các nguồn có thẩm quyền sao lưu tôi không? Cá nhân của bạn nhận gì về điều này và tại sao? Tôi có thể nói gì với các đồng nghiệp muốn thiết kế với các tham số đầu ra có thể thuyết phục họ sử dụng các cấu trúc khác nhau?

CHỈNH SỬA: biến thú vị- thông số đầu ra mà tôi đã hỏi câu hỏi này được sử dụng thay cho giá trị trả lại. Khi giá trị trả về là "L ERI", người gọi được cho là xử lý nó như một ngoại lệ. Tôi đã làm điều đó nhưng không hài lòng với ý tưởng đó. Một đồng nghiệp đã không được thông báo về sự cần thiết phải xử lý tình trạng này và kết quả là, rất nhiều tiền đã bị mất khi thủ tục thất bại âm thầm!

+1

Đây là chủ đề và phải là cộng đồng wiki để tiếp tục tồn tại. Tôi lưu ý rằng đã có một hit gần. Tôi sẽ không đóng trừ khi bạn không đánh dấu CW. – Randolpho

+4

Tôi biết điều gì, nhưng điều này nghe với tôi như một câu hỏi công bằng về thương mại thiết kế. – JeffH

+0

đã thay đổi thẻ để bao gồm tham chiếu sql + vb trong các câu hỏi – gbn

Trả lời

11

Bob Martin đã viết về Bộ luật sạch này. Các tham số đầu ra phá vỡ ý tưởng cơ bản của một hàm.

output = someMethod(input)

+0

Một proc được lưu trữ không phải là một chức năng mặc dù, nhưng tôi hiểu lý do – gbn

+0

trông giống như liên kết đến Bob Martin bây giờ đã chết. – PaulBinder

27

Thông số đầu ra có thể là một mã số cho biết phương thức của bạn đang hoạt động quá nhiều. Nếu bạn cần trả về nhiều hơn một giá trị, phương thức này có khả năng làm nhiều hơn một điều. Nếu dữ liệu có liên quan chặt chẽ, thì có lẽ nó sẽ được hưởng lợi từ một lớp chứa cả hai giá trị.

Tất nhiên, điều này không phải luôn luôn như vậy, nhưng tôi thấy rằng đó thường là trường hợp.

Nói cách khác, tôi nghĩ bạn có quyền tránh chúng.

0

Tôi thường không bao giờ sử dụng chúng, tôi nghĩ chúng rất khó hiểu và quá dễ bị lạm dụng. Thỉnh thoảng, chúng tôi sử dụng các tham số ref nhưng điều đó có liên quan nhiều hơn đến việc chuyển các cấu trúc và nhận lại chúng.

0

Ý kiến ​​của bạn hợp lý với tôi.

Một nhược điểm khác của thông số đầu ra là mã bổ sung cần thiết để chuyển kết quả từ hàm này sang hàm khác. Bạn phải khai báo (các) biến, gọi hàm để lấy giá trị của chúng, và sau đó chuyển các giá trị cho một hàm khác. Bạn không thể chỉ tổ chức các cuộc gọi chức năng. Điều này làm cho mã đọc rất độc, thay vì khai báo.

1

Tôi nghĩ họ là hữu ích để nhận ID của hàng mới được chèn vào trong lệnh cùng một SQL, nhưng tôi không nghĩ rằng tôi đã sử dụng chúng cho nhiều người khác.

0

C++ 0x đang nhận bộ dữ liệu, một cấu trúc giống như cấu trúc ẩn danh, có thành viên mà bạn truy cập theo chỉ mục. Lập trình viên C++ sẽ có thể đóng gói nhiều giá trị vào một trong số đó và trả lại. C# có cái gì như thế không? Nó có thể trả về một mảng, có lẽ, thay vào đó? Nhưng các thông số đầu ra có một chút khó xử và không rõ ràng.

+0

C# có thể trả về một mảng dễ dàng. Nhưng trả về một mảng (mà về bản chất là bộ tuple là gì) dường như với tôi khá phi ngữ nghĩa, và có thể dễ dàng bị lẫn lộn. Nếu bạn luôn trả về cùng một tập hợp các giá trị, thì các biến số có vẻ là lựa chọn tốt hơn cho tôi. –

+3

C# 4.0 sẽ giới thiệu một tính năng rất sáng tạo ... Tuple :) –

+0

Gotta thích nó! : P –

20

Họ có vị trí của họ. Phương pháp Int32.TryParse là một ví dụ tốt về việc sử dụng hiệu quả tham số ngoài.

bool result = Int32.TryParse(value, out number); 
if (result) 
{ 
    Console.WriteLine("Converted '{0}' to {1}.", value, number);   
} 
+1

Ví dụ hay. TryParse là một trong những phương pháp duy nhất tôi từng thấy sử dụng * và * là hợp lý khi làm như vậy. – Jagd

+0

Đó là một trường hợp đặc biệt thú vị, bởi vì TryParse() tồn tại để tránh khả năng của một ngoại lệ khi giá trị không chứa một int. – JeffH

+10

Cá nhân tôi muốn "int? Int32.TryParse (chuỗi giá trị)" như chữ ký, bởi vì sau đó bạn có thể sử dụng ?? toán tử để xác định các giá trị dự phòng. Nhưng chức năng này được viết trước khi Nullables được giới thiệu. – Jimmy

1

tôi cũng thấy rất ít sử dụng các thông số ra/ref, mặc dù trong SQL đôi khi nó dễ dàng hơn để vượt qua một giá trị trở lại bởi một tham số hơn bởi một resultset (mà sau đó sẽ đòi hỏi việc sử dụng một DataReader, vv .)

Mặc dù, vì may mắn sẽ có nó, tôi vừa tạo ra một chức năng hiếm hoi như vậy trong C# hôm nay. Nó đã xác nhận cấu trúc dữ liệu giống như bảng và trả về số hàng và cột trong đó (điều này rất khó để tính toán vì bảng có thể có các hàng rào/colspans như trong HTML). Trong trường hợp này việc tính toán cả hai giá trị được thực hiện cùng một lúc. Tách nó thành hai chức năng sẽ dẫn đến việc tăng gấp đôi mã, bộ nhớ và các yêu cầu về thời gian của CPU. Tạo một loại tùy chỉnh chỉ cho một chức năng này để trở về cũng có vẻ như một overkill cho tôi.

Vì vậy, có những lúc chúng là điều tốt nhất, nhưng phần lớn bạn có thể làm tốt mà không cần đến chúng.

1

Điều khoản OUTPUT trong SQL Server 2005 trở đi là bước tiến lớn để nhận được bất kỳ giá trị trường nào cho các hàng bị ảnh hưởng bởi các câu lệnh DML của bạn. Ithink rằng có rất nhiều tình huống mà điều này không đi với các thông số đầu ra.

Trong VB6, các tham số ByRef phù hợp để truyền các đối tượng ADO.

ngoài hai trường hợp cụ thể mà bạn nghĩ đến, tôi có xu hướng tránh sử dụng chúng.

1

Chỉ trong SQL ...

Thông số đầu ra quy trình được lưu trữ hữu ích.

  1. Giả sử bạn cần một giá trị trở lại. Bạn có "tạo #table, chèn ... exec, chọn @var =" không. Hoặc sử dụng một tham số đầu ra?

  2. Đối với các cuộc gọi của khách hàng, thông số đầu ra nhanh hơn nhiều so với xử lý bản ghi.

  3. Sử dụng giá trị RETURN được giới hạn ở số nguyên đã ký.

  4. dễ dàng hơn để tái sử dụng (ví dụ như một thủ tục kiểm tra an ninh helper)

  5. Khi sử dụng cả hai: recordset = dữ liệu, thông số output = status/tin nhắn/rowcount vv

  6. thủ tục lưu trữ đầu ra recordset có thể không được mạnh mẽ gõ như UDFs hoặc khách hàng đang

  7. Bạn có thể không luôn luôn sử dụng một UDF (ví dụ như khai thác gỗ trong kiểm tra an ninh ở trên)

Tuy nhiên, miễn là bạn thường không sử dụng cùng một tham số cho đầu vào và đầu ra, thì cho đến khi SQL thay đổi hoàn toàn các tùy chọn của bạn bị giới hạn. Nói rằng, tôi có một trường hợp mà tôi sử dụng một paramter cho các giá trị vào và ra, nhưng tôi có một lý do chính đáng.

1

Hai số của tôi:
Tôi đồng ý rằng thông số đầu ra là một thực tiễn liên quan. VBA thường được duy trì bởi những người rất mới để lập trình và nếu ai đó duy trì mã của bạn không nhận thấy rằng một tham số là ByRef họ có thể giới thiệu một số lỗi logic nghiêm trọng. Ngoài ra nó có xu hướng phá vỡ mô hình Property/Function/Sub.
Một lý do khác khiến việc sử dụng tham số là thực tế xấu là nếu bạn thực sự cần phải trả lại nhiều giá trị, có thể bạn nên có các giá trị đó trong cấu trúc dữ liệu như lớp học hoặc Loại do người dùng xác định.
Tuy nhiên, họ có thể giải quyết một số vấn đề.VB5 (và do đó VBA cho Office 97) không cho phép một hàm trả về một mảng. Điều này có nghĩa là bất cứ điều gì trở lại hoặc thay đổi một mảng sẽ phải làm như vậy thông qua một tham số "out". Trong VB6 khả năng này đã được thêm vào, nhưng VB6 vẫn buộc các tham số mảng được tham chiếu (để ngăn chặn việc sao chép quá mức trong bộ nhớ). Bây giờ bạn có thể trả về một giá trị từ một hàm làm thay đổi mảng. Nhưng nó sẽ chỉ là một mái tóc chậm (do những nhào lộn đang diễn ra đằng sau hậu trường); nó cũng có thể gây nhầm lẫn cho người mới nghĩ rằng đầu vào mảng sẽ không bị thay đổi (điều này sẽ chỉ đúng nếu ai đó cấu trúc nó theo cách đó). Vì vậy, tôi thấy rằng nếu tôi có một chức năng thay đổi một mảng nó làm giảm sự nhầm lẫn để chỉ sử dụng một phụ thay vì một chức năng (và nó sẽ là một chút nhỏ hơn quá).
Một trường hợp khác có thể là nếu bạn đang duy trì mã và bạn muốn thêm giá trị ngoài mà không vi phạm giao diện, bạn có thể thêm tham số tùy chọn và tự tin rằng bạn sẽ không vi phạm bất kỳ mã cũ nào. Nó không phải là thực hành tốt, nhưng nếu ai đó muốn một cái gì đó cố định ngay bây giờ và bạn không có thời gian để làm điều đó "đúng cách" và cơ cấu lại mọi thứ, điều này có thể là một bổ sung tiện dụng vào hộp công cụ của bạn.
Tuy nhiên, nếu bạn đang phát triển mọi thứ từ đầu và bạn cần phải trả lại nhiều giá trị, bạn nên cân nhắc:
1. Phá vỡ hàm.
2. Trả lại UDT.
3. Trả lại lớp học.

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