Tại sao 'void' không được phép làm loại chung trong C #


53

Các quyết định thiết kế lập luận ủng hộ việc voidkhông thể xây dựng và không được phép là một loại chung là gì? Sau khi tất cả nó chỉ là một sản phẩm nào đặc biệt structvà có thể tránh được tổng Pita của việc có khác nhau FuncActioncác đại biểu.

(C ++ cho phép voidtrả về rõ ràng và cho phép voiddưới dạng tham số mẫu)


13
@Oded Xem xét rằng Eric Lippert có tài khoản và tham gia vào Lập trình viên , tôi nghĩ anh ấy đã làm.
Thomas Owens

2
@BenVoigt Không nhất thiết phải có kiến ​​thức của một cá nhân, mặc dù có một người duy nhất ở đây có thể (một cách dễ dàng, tôi cho rằng) đưa ra câu trả lời đúng. Bất cứ ai quen thuộc với đặc tả kỹ thuật có thể trả lời câu hỏi, đặc biệt nếu họ có kiến ​​thức về thiết kế ngôn ngữ lập trình. Đây cũng là một câu hỏi thiết kế ngôn ngữ / thiết kế ngôn ngữ thú vị, có chủ đề ở đây.
Thomas Owens

6
@BenVoigt: Tại sao bạn rất muốn có một câu hỏi hoàn toàn hợp lệ và thú vị được đóng lại mà không có lý do chính đáng, khác để thỏa mãn công việc sư phạm của riêng bạn? Tôi đã có một tìm kiếm và không thể tìm thấy câu trả lời; có thể ai đó ở đây đã đọc một bài đăng trên blog về nó, có thể những người đưa ra quyết định muốn trả lời câu hỏi, có thể ai đó đã trò chuyện với những người đưa ra quyết định về điều này và tự đặt câu hỏi và có thể chuyển câu trả lời. Tôi đã ngừng đăng bài trên trang này và SO khá nhiều vì mọi người dường như quan tâm nhiều hơn đến việc đóng một câu hỏi hơn là trả lời các câu hỏi.

4
Tôi có thể chỉ ra các câu hỏi và câu trả lời "điểm lớn" ở đây và đặc biệt là về SO thường có dạng "cú pháp này có nghĩa là gì?" Những câu hỏi đó hầu như không bao giờ bị đóng bởi vì tất cả mọi người có thể chồng chất và đưa ra các định nghĩa cho các nhà thơ cấu thành các đối tượng const. Các câu hỏi thú vị hơn nằm ngoài đường đua bị đánh bật ra khỏi trang web vì một số lý do mang tính mô phạm: nghiêm túc chỉ là một vài kilobyte trong kho dữ liệu ở đâu đó. Tất cả chúng ta có thể thư giãn và nắm lấy việc học hơn là áp đặt các quy tắc diễn giải tùy tiện phục vụ cho mục đích rất ít?

2
@ThomasOwens: Tôi có ý nghĩa tích cực hơn trên trang web này so với SO. Trên trang web này, tôi đăng một câu trả lời cho khoảng một câu hỏi trong mỗi 300. Trên SO tôi đăng một câu trả lời cho khoảng một câu hỏi trong mỗi 1500. Sự khác biệt trong hoạt động số lượng câu trả lời là do số lượng cơ hội cao hơn nhiều cho trả lời câu hỏi C # về SO.
Eric Lippert

Câu trả lời:


69

Vấn đề cơ bản với "void" là nó không có nghĩa giống như bất kỳ loại trả lại nào khác. "void" có nghĩa là "nếu phương thức này trả về thì nó không trả về giá trị nào cả." Có giá trị; null là một giá trị Nó trả về không có giá trị gì.

Điều này thực sự gây rối hệ thống loại. Một hệ thống loại về cơ bản là một hệ thống để thực hiện các suy luận logic về những hoạt động nào là hợp lệ trên các giá trị cụ thể; một phương thức trả về void không trả về một giá trị, vì vậy câu hỏi "hoạt động nào là hợp lệ đối với điều này?" không có ý nghĩa gì cả Không có "điều" nào để có một hoạt động trên, hợp lệ hoặc không hợp lệ.

Hơn nữa, điều này làm rối loạn thời gian chạy một cái gì đó dữ dội. Thời gian chạy .NET là một triển khai của Hệ thống thực thi ảo, được chỉ định là một máy xếp chồng. Đó là, một máy ảo trong đó tất cả các hoạt động được đặc trưng về hiệu ứng của chúng trên một ngăn xếp đánh giá. (Tất nhiên trong thực tế máy sẽ được thực hiện trên một máy với cả chồng và đăng ký, nhưng hệ thống thực hiện ảo giả chỉ một chồng.) Hiệu quả của một cuộc gọi đến một phương pháp khoảng trống là cơ bảnkhác với hiệu quả của một cuộc gọi đến một phương thức không trống; một phương thức không trống luôn đặt một cái gì đó lên ngăn xếp, có thể cần phải bật ra. Một phương thức void không bao giờ đặt một cái gì đó lên ngăn xếp. Và do đó, trình biên dịch không thể xử lý các phương thức void và non-void giống nhau trong trường hợp giá trị trả về của phương thức bị bỏ qua; nếu phương thức là void thì không có giá trị trả về nên không có pop.

Vì tất cả những lý do này, "void" không phải là một loại có thể được khởi tạo; nó không có giá trị , đó là toàn bộ quan điểm của nó. Nó không thể chuyển đổi thành đối tượng và một phương thức trả về khoảng trống không bao giờ có thể được xử lý đa hình bằng phương thức trả về không có giá trị vì làm như vậy làm hỏng ngăn xếp!

Do đó, void không thể được sử dụng như một đối số kiểu, đó là một sự xấu hổ, như bạn lưu ý. Nó sẽ rất thuận tiện.

Với lợi ích của nhận thức muộn, sẽ tốt hơn cho tất cả những người quan tâm nếu thay vì không có gì, một phương thức trả về khoảng trống tự động trả về "Đơn vị", một loại tham chiếu đơn lẻ ma thuật. Sau đó , bạn sẽ biết rằng mọi cuộc gọi phương thức đều đặt một thứ gì đó lên ngăn xếp , bạn sẽ biết rằng mọi cuộc gọi phương thức đều trả về một thứ có thể được gán cho một biến của loại đối tượng và dĩ nhiên Đơn vị có thể được sử dụng làm đối số kiểu , do đó sẽ có không cần phải có các loại đại biểu Hành động và Func riêng biệt. Đáng buồn thay, đó không phải là thế giới chúng ta đang ở.

Đối với một số suy nghĩ trong tĩnh mạch này xem:


C ++ hỗ trợ nó mà không phải sử dụng một loại singleton ma thuật. Nhưng tôi cho rằng phải làm với C ++ bằng cách sử dụng kiểu "generic" hoàn toàn khác với C #.
Winston Ewert

4
@WinstonEwert - Tôi khá chắc chắn C ++ hoàn toàn không hỗ trợ thuốc generic, mà thay vào đó có các mẫu, về cơ bản là khác nhau. Theo tôi hiểu, với các mẫu trình biên dịch đang thực hiện tìm kiếm toàn cầu và thay thế bằng các tham số loại của bạn, nhưng với khái quát, hệ thống loại đang tạo ra một loại thích hợp. Tôi cũng nghĩ đó là lý do tại sao các lỗi mẫu C ++ rất khó hiểu. Tôi chắc chắn Eric sẽ sửa lỗi cho tôi nếu tôi nói bất cứ điều gì không hoàn toàn đúng
Adam Rackis

1
Tôi nghĩ rằng tất cả các cấu trúc được xử lý tại thời điểm biên dịch để có được vị trí thích hợp trên ngăn xếp và ở những nơi khác mà chúng được nội tuyến. Do đó, Voidsẽ ổn khi được truyền dưới dạng vô số đối số bên trong 0 byte stack. Khi bất kỳ cấu trúc nào cần chuyển đổi sang objecthoặc gọi phương thức (để nhận this), nó được đóng hộp với việc đặt trên heap với Typetham chiếu được chèn trước vùng trường của bộ nhớ (đối với nhiều triển khai CLR) và do đó có thể được xử lý đúng cách. Đối với tôi loại chỉ là một nhóm các đối tượng có thể được phân biệt bởi một số đặc điểm (các trường). Voidchỉ là một đối tượng.
ony

1
@ OlivierJacot-Descombes: Nếu voidlà một loại giá trị trống, thì câu lệnh đó sẽ chuyển thành không có hướng dẫn về mã máy. Không hữu ích cho loại mã hóa cứng Void, nhưng hữu ích trong trường hợp một loại có nhiều tham số chung nhưng một số không cần thiết trong một số trường hợp nhất định.
supercat

2
@EricLippert: Việc xử lý đúng các giá trị trả về loại giá trị sẽ yêu cầu khả năng bật một số lượng từ thay đổi khỏi ngăn xếp. Sẽ có bất kỳ khó khăn cơ bản nào với việc cho phép số lượng từ bằng không? Nếu người gọi chịu trách nhiệm phân bổ không gian và vượt qua byref, hệ thống loại sẽ phải nhận ra rằng void byref không có ý nghĩa gì và có lẽ điều đó không được coi là đáng để nỗ lực, nhưng tôi không thấy bất kỳ vấn đề "cơ bản" nào .
supercat

9

Từ: http://connect.microsoft.com/VisualStudio/feedback/details/94226/allow-void-to-be-parameter-of-generic- class-if-not-in-c-then-just-in- thời gian chạy

Đây thực sự là do thiết kế - chúng tôi không cho phép bất kỳ trường hợp nào của loại khoảng trống (cùng với nhiều loại khác trong thời gian chạy). Bạn cũng không thể tạo ra một khoảng trống hoặc khoảng trống []. Chúng tôi cắm các loại lỗ này để bảo mật.

Cả đời tôi không thể thấy khoảng trống là lỗ hổng bảo mật, nhưng ... nó nói như vậy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.