简体   繁体   中英

Why can I not type cast Interface into its concrete implementation?

Here is a very trivial problem that seems rather annoying due to my lack of experience but, why can I not do something like this:

 public interface INetworkMessage { ... }
 public class NetworkDataMessage : INetworkMessage { ... }

 public void ParseMessage (INetworkMessage message)
 {
     Type concreteMessageType = message.GetType();
     var concreteMessageInstance = message as concreteMessageType;
     ...
     // Now in theory I could work with a concrete type?
 }

To answer your question: you can directly cast the object using a cast operation and the compile-time type name:

var concreteMessageInstance = (NetworkDataMessage)message; //may throw InvalidCastException for different implementation of INetworkMessage

Or

var concreteMessageInstance = message as NetworkDataMessage;
if(concreteMessageInstance != null) { /* ... */ }

However: you should rethink your design if you need a concrete implementation from an interface. The whole idea of the interface is that the details don't matter - maybe the thing you're trying to do on the concrete type should be moved into the interface? Or maybe you should use the concrete type directly instead and skip out on the interface? Both are design decisions you should consider.

If you want to be able to cast to any concrete implementation of the interface dynamically and invoke some operation, then you DEFINITELY should move the operation from the concrete type to the interface. The cast just adds extra overhead and a well-designed application would have such an operation in the interface definition from the start.

You can only use as to cast to a type which you specify at compile time (either directly or via generics). Your code won't compile.

Since you don't know at compile time what concreteMessageType is, you also can't use concreteMessageInstance (if such a cast were possible), since the methods/properties/fields/etc. you would use need to be known by the compiler.

I ended up following David's suggestion in my own way:

public void ParseMessage<T> (INetworkMessage message) where T : INetworkMessage
 {
   // So now I can do
   var concreteInstance = (T)message;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM