Jakie były decyzje projektowe, które przemawiały za tym, że void
nie można ich zbudować i że nie można ich uznać za rodzaj ogólny? W końcu jest to po prostu specjalny pusty struct
i uniknąłby całkowitej PITA posiadania odrębnych Func
i Action
delegatów.
(C ++ pozwala na jawne void
zwroty i pozwala void
jako parametr szablonu)
c#
.net
language-design
Thomas Owens
źródło
źródło
Odpowiedzi:
Podstawowym problemem związanym z „void” jest to, że nie oznacza to tego samego, co każdy inny typ zwrotu. „void” oznacza „jeśli ta metoda zwróci, to nie zwróci żadnej wartości”. Nie jest zerem; null jest wartością. Nie zwraca żadnej wartości.
To naprawdę psuje system typów. System typów jest zasadniczo systemem do dokonywania logicznych dedukcji dotyczących tego, jakie operacje są poprawne dla poszczególnych wartości; nieważna metoda zwracająca wartość nie zwraca wartości, więc pytanie „jakie operacje są poprawne w tej sprawie?” nie ma żadnego sensu. Nie ma „rzeczy”, aby istniała operacja, ważna lub nieprawidłowa.
Co więcej, to zepsuło środowisko uruchomieniowe coś gwałtownego. Środowisko wykonawcze .NET jest implementacją wirtualnego systemu wykonawczego, który jest określony jako maszyna stosowa. Oznacza to maszynę wirtualną, w której wszystkie operacje są scharakteryzowane pod względem ich wpływu na stos oceny. (Oczywiście w praktyce maszyna zostanie zaimplementowana na maszynie ze stosem i rejestrami, ale wirtualny system wykonawczy przyjmuje tylko stos.) Efekt wywołania metody void jest zasadniczoinny niż efekt wywołania metody innej niż void; metoda nie void zawsze kładzie coś na stosie, co może wymagać oderwania. Metoda void nigdy nie kładzie czegoś na stosie. Dlatego kompilator nie może traktować metod void i non-void tak samo w przypadku, gdy zwracana wartość metody jest ignorowana; jeśli metoda jest nieważna, nie ma wartości zwracanej, więc nie może być pop.
Z tych wszystkich powodów „void” nie jest typem, który można utworzyć; nie ma żadnych wartości , o to właśnie chodzi. Nie można go przekształcić w obiekt, a metody zwracania pustek nigdy nie można nigdy traktować polimorficznie za pomocą metody nie zwracającej pustki, ponieważ powoduje to uszkodzenie stosu!
Dlatego void nie może być użyty jako argument typu, co jest wstydem, jak zauważasz. Byłoby to bardzo wygodne.
Z perspektywy czasu byłoby lepiej dla wszystkich zainteresowanych, gdyby zamiast niczego metoda zwracania pustek automatycznie zwracała „Unit”, magiczny typ odniesienia singletonu. Wiedziałbyś wtedy, że każde wywołanie metody umieszcza coś na stosie , wiedziałbyś, że każde wywołanie metody zwraca coś, co można przypisać do zmiennej typu obiektu , i oczywiście Unit może być użyty jako argument typu , więc byłoby nie trzeba mieć osobnych typów delegatów Action i Func. Niestety, nie w tym świecie się znajdujemy.
Aby uzyskać więcej przemyśleń w tym duchu, zobacz:
źródło
Void
powinno być ok, aby było przekazywane jako nieskończona ilość argumentów wewnątrz 0 bajtów stosu. Gdy jakakolwiek struktura wymaga konwersjiobject
lub wywołania metody (w celu uzyskaniathis
), jest umieszczana w ramce z umieszczaniem na stercie zType
odniesieniem wstawionym przed polami pamięci (dla wielu implementacji CLR), a zatem może być poprawnie obsługiwana. Jak dla mnie typ to tylko grupowanie obiektów, które można rozróżnić za pomocą niektórych cech (pól).Void
jest tylko jednym przedmiotem.void
był pustym typem wartości, wówczas instrukcja ta przełożyłaby się na zero instrukcji kodu maszynowego. Niezbyt przydatne dla typu zakodowanego na stałeVoid
, ale przydatne w przypadkach, gdy typ ma wiele ogólnych parametrów, ale niektóre nie są potrzebne w niektórych przypadkach.Od: http://connect.microsoft.com/VisualStudio/feedback/details/94226/allow-void-to-be-parameter-of-generic-class-if-not-in-c-then-just-in- środowisko uruchomieniowe
Nie mogę z mojego życia zobaczyć, jak pustka jest dziurą w zabezpieczeniach, ale ... tak to mówi.
źródło