为什么我不能在其具体实现中输入强制转换接口?

时间:2015-11-24 21:12:40

标签: c# interface casting

由于我缺乏经验,这是一个非常微不足道的问题,但为什么我不能做这样的事情:

 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?
 }

3 个答案:

答案 0 :(得分:4)

回答你的问题:你可以使用强制转换操作和编译时类型名称直接转换对象:

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

或者

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

但是:如果需要从界面中进行具体实现,则应重新考虑您的设计。接口的整个想法是细节无关紧要 - 也许你想要在具体类型上做的事情应该移到界面中?或者也许您应该直接使用具体类型并跳过界面?两者都是您应该考虑的设计决策。

如果您希望能够动态地转换为接口的任何具体实现并调用某些操作,那么您肯定应该将操作从具体类型移动到接口。演员表只是增加了额外的开销,而设计良好的应用程序从一开始就会在接口定义中进行这样的操作。

答案 1 :(得分:1)

您只能使用as强制转换为您在编译时指定的类型(直接或通过泛型)。您的代码将无法编译。

由于您在编译时不知道concreteMessageType是什么,因此您也无法使用concreteMessageInstance(如果可以进行此类转换),因为方法/ properties / fields / etc。你需要使用编译器知道。

答案 2 :(得分:0)

我最终以自己的方式追随大卫的建议:

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