【问题标题】:Permanent casting to a superclass永久转换为超类
【发布时间】:2011-05-02 12:05:51
【问题描述】:

如果:

class Car : Automobile
{}

我能做到:

Car toyota = new Car();
Automobile tauto = (Automobile)toyota;

但如果我使用tauto.GetType().Name,它仍然是汽车

是否可以执行强制转换,以便将类型永久更改为汽车(无需克隆对象)?

我要克服的问题是 C# 中没有多重继承,我需要以一种方法合并来自 2 个服务的对象(具有相同的签名),并返回一种类型。

【问题讨论】:

  • 只是好奇:你为什么要这样做?
  • 很抱歉,您为什么要这样做?对象汽车,而不是汽车。如果你想要一辆汽车,然后实例化一个。
  • 长话短说,但它涉及实体框架、POCO,以及它无法使用相同的 POCO 类来由 2 个不同的实体集返回。所以我必须通过继承来解决这个问题。但在外面,我希望两个视图中的对象是相同的。所以只需返回超类。简单的转换是有问题的,因为像 WCF 序列化器和 .net 3.5 泛型之类的东西仍然将转换对象视为子类
  • 听起来你的 DataContext 的设计可能是另一个问题的主题,因为实际问题不是关于转换对象,而是关于 EF。

标签: c# oop inheritance clone


【解决方案1】:

没有。如果不构造 new 汽车对象,就无法做到这一点。

但是,也没有理由这样做。 Liskov substitution principle 表示任何 Car 都应该始终像 Automobile 一样可处理,并且用户的预期行为不应发生变化。

只要您正确设计类层次结构,使用Car 作为Automobile 应该总是完全可以接受的。


附带说明:这就是为什么使用Type.GetType() 不是检查类型的首选方法的部分原因。在 C# 中使用 isas 关键字更安全、更好。如果您检查 tauto is Car,它们将返回 true。

【讨论】:

  • 不幸的是 wcf 序列化器关心,3.5 泛型也关心.. 所以我不能简单地更改该代码.. 我知道我可以提供自己的序列化,但它让我到处都感到头疼..
  • 3.5 泛型不在乎 - 诚然,WCF 序列化存在一些潜在问题,尽管这种情况很少见,无论如何你都应该让你的类可序列化。如果你真的需要让它成为一个子类,你需要构造一个新对象。只需在汽车上创建一个像这样的新构造函数:public Automobile(Automobile other),然后您可以在传递给真正关心的例程时创建它......
【解决方案2】:

根据MSDN,您只是将引用投射到对象,而不是底层对象。

【讨论】:

    【解决方案3】:

    您的问题和您想要做的事情似乎是两件不同的事情。不,您不能更改对象的基础类型。但是您似乎想要做的是创建一种具有一组属性的汽车,而不是实际使用子类。你可以做的是改用汽车工厂。

    public static class AutomobileFactory()
    {
       public static Automobile CreateAutomobile(AutomobileType type)
       {
         ...   
       } 
    }
    

    AutomobileType 是一个枚举。有关更多信息,请访问谷歌 C# 工厂模式。

    【讨论】:

      【解决方案4】:

      我不确定你到底想要做什么,但也许你可以考虑一种不同的方法?与其尝试使用继承合并两个不同类的功能,不如使用组合?

      http://tiedyedfreaks.org/eric/CompositionVsInheritance.html

      public class Service
      {
          public virtual void DoSomething()
          {
      
          }
      }
      
      public class ServiceA : Service
      {
          public override void DoSomething()
          {
      
          }
      }
      
      public class ServiceB : Service
      {
          public override void DoSomething()
          {
      
          }
      }
      
      public class ServiceA_B : Service
      {
          ServiceA serviceA = new ServiceA();
          ServiceB serviceB = new ServiceB();
      
          public override void DoSomething()
          {
              serviceA.DoSomething();
              serviceB.DoSomething();   
          }
      }
      

      【讨论】:

        【解决方案5】:

        在某些情况下,泛型可能会有所帮助。如果方法包含泛型参数,则泛型类型将被评估为传入引用的声明类型,而不是传入对象的类型。例如:

        void Foo(T 条)

        如果使用 (Control)someButton 调用 foo(),'bar' 的类型将是 Button,但 T 的类型将是 Control。

        【讨论】:

          猜你喜欢
          • 2011-06-30
          • 1970-01-01
          • 1970-01-01
          • 2020-05-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-26
          • 1970-01-01
          相关资源
          最近更新 更多