【问题标题】:Why can I not type cast Interface into its concrete implementation?为什么我不能在其具体实现中键入 cast Interface?
【发布时间】:2015-11-24 21:12:39
【问题描述】:

这是一个非常琐碎的问题,由于我缺乏经验,看起来很烦人,但是,为什么我不能这样做:

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

【问题讨论】:

  • 可以,但一般来说你不应该。如果你必须这样做,那么这通常表明你的设计有问题。如果支持类型不是您期望的类型,尝试这样做会带来风险。
  • 因为INetworkMessage不一定是NetworkDataMessage,它可以是它的任何实现,那么你怎么知道要转换成哪个具体类型呢?
  • @RonBeyer 但 GetType() 不返回确切的具体类型?
  • @David 再次查看代码,他尝试使用GetType 获取类型,然后使用as 将其转换为变量。此代码不会编译。它不是伪代码,concreteMessageType 是一个变量。
  • @eYe:一个例子,究竟是什么?您需要考虑系统的架构并确定此方法需要做什么以及它如何适合您的整个系统。如果该方法需要NetworkDataMessage 的实例,则接受该类型的参数。如果它需要INetworkMessage 的实例,则接受该类型的参数。您在问题中提出的问题是解决您最初不应该遇到的问题的症状。

标签: c# interface casting


【解决方案1】:

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

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

或者

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

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

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

【讨论】:

    【解决方案2】:

    您只能使用as 转换为您在编译时指定的类型(直接或通过泛型)。你的代码不会编译。

    由于您在编译时不知道concreteMessageType 是什么,因此您也不能使用concreteMessageInstance(如果可以进行这种转换),因为方法/属性/字段/等。你会使用需要被编译器知道。

    【讨论】:

      【解决方案3】:

      我最终以自己的方式遵循了大卫的建议:

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

      【讨论】:

      • 但这对您有什么帮助?通过强制转换为 T,你真的不能做更多的事情。
      猜你喜欢
      • 1970-01-01
      • 2014-08-15
      • 2013-03-07
      • 2012-01-09
      • 2012-08-31
      • 2011-01-20
      • 2013-01-27
      • 1970-01-01
      • 2012-11-10
      相关资源
      最近更新 更多