I think it is not so much about raw speed (although this is certainly important) as it is about reliability. Raw speed (and, in general, runtime efficiency) is usually a corollary of elegance in design.
Now that we have programming languages with linear types and static lifetime management (Rust), I think it is fair to say garbage-collected systems have "duck-typed lifetimes" and languages with raw pointers have "untyped lifetimes".
And here is the catch: The principle that duck typing adds overhead (unacceptable for systems programming) does not only apply to values (in the form of the "type tag" that every value must carry), it applies to lifetimes as well (in the form of garbage collection pauses)!
Furthermore, I strongly suspect the aforementioned principle applies to anything worthy of being expressed statically. Off of the top of my head: validity of indices for sequential containers and keys for associative containers, which requires dependent types to be expressed statically, and whose duck typing counterpart is throwing something like .NET's ArgumentOutOfRangeException or KeyNotFoundException.
- C# syntactic sugar
- As fast as C++
- Does not require .NET
- Runs on Windows/Linux/Unix with no problems