void như một loại . Tại sao trên trái đất là "void" một loại? Nó không có phiên bản, nó không có giá trị, bạn không thể sử dụng nó làm đối số loại chung, loại tham số chính thức, loại cục bộ, loại trường hoặc loại thuộc tính. Nó không có ý nghĩa như một loại; đúng hơn, đó là một thực tế về tác động của một cuộc gọi phương thức đối với ngăn xếp của máy ảo. Nhưng máy ảo chỉ có thế: một máy ảo. Máy thật sẽ đặt giá trị trả về vào một thanh ghi (thường là EAX trên x86) và hoàn toàn không ảnh hưởng đến ngăn xếp! Vô hiệu như một loại chỉ là một ý tưởng tồi xung quanh.
Tệ hơn: khi được sử dụng trong một loại con trỏ như trong void*
nó có nghĩa là một cái gì đó hoàn toàn khác với những gì nó có nghĩa là khi được sử dụng như một loại trả về. Bây giờ nó có nghĩa là "một con trỏ đến một vị trí lưu trữ không xác định", không liên quan gì đến ý nghĩa của nó là "một phương thức không trả về bất kỳ giá trị nào".
Chúng ta có thể thay thế void*
như một loại con trỏ với IntPtr
. (Và void**
với IntPtr*
và vân vân.) Chúng tôi có thể thay thế khoảng trống như một kiểu trả về với "Đơn vị", một loại mà có một giá trị duy nhất, cụ thể là, null. Việc triển khai CLR sau đó có thể quyết định rằng một lệnh gọi hàm đơn vị có thể tối ưu hóa việc sử dụng các thanh ghi hoặc ngăn xếp của nó một cách thích hợp, biết rằng null được "trả về" có thể được bỏ qua một cách an toàn.
Trong một thế giới như vậy, bạn không còn cần tách biệt Func<A, R>
và Action<T>
đại biểu. Action<T>
chỉ là Func<T, Unit>
.