As explained by Neal Gafter from Microsoft:
The reason it doesn’t work is that there is no conversion (explicit or implicit) defined from T to KeepalivePacket. Pattern matching requires such a conversion to exist, as it is defined in terms of the cast operator, which requires a conversion exist. The language specification and compiler agree that no conversion exists. It seems strange to me that the language specification is defined such that no (explicit) conversion exists here. We’ll look at what we can do about that.
We’re not going to do anything about this in C# 7. You’ll have to add a cast to your code to work around it. Once we have recursive patterns, this may be more difficult to work around. Moreover, the awkward language rule that underlies this issue (i.e. that there is no conversion from T to KeepalivePacket) doesn’t make a lot of sense.
Update
This is now working in C# 7.1