void come tipo . Perché sulla terra è "vuoto" un tipo? Non ha istanze, non ha valori, non puoi usarlo come argomento di tipo generico, tipo di parametro formale, tipo locale, tipo di campo o tipo di proprietà. Non ha significato come tipo; piuttosto, è un dato di fatto su quale effetto ha una chiamata di metodo sullo stack della macchina virtuale. Ma la macchina virtuale è proprio questa: una macchina virtuale. La macchina reale metterà il valore restituito in un registro (tipicamente EAX su x86) e non influenzerà affatto lo stack! Il vuoto come tipo è solo una cattiva idea tutt'intorno.
Peggio: se usato in un tipo di puntatore come in void* , significa qualcosa di completamente diverso di quello che significa quando viene usato come tipo di ritorno. Ora significa "un puntatore a una posizione di archiviazione di tipo sconosciuto", che non ha assolutamente nulla a che fare con il suo significato come "un metodo che non restituisce alcun valore."
Possiamo sostituire void* come un tipo di puntatore con IntPtr . (E void** con IntPtr* e così via.) Possiamo sostituire void come un tipo di ritorno con "Unit", un tipo che ha un valore singolo, vale a dire null. Un'implementazione del CLR potrebbe quindi decidere che una chiamata di funzione digitata in unità potrebbe ottimizzare l'utilizzo dei registri o degli stack in modo appropriato, sapendo che il valore null "restituito" può essere tranquillamente ignorato.
In un mondo del genere non hai più bisogno di delegati separati Func<A, R> e Action<T> . Action<T> è solo Func<T, Unit> .