【问题标题】:Cast derived class to another derived in c#将派生类转换为 C# 中的另一个派生类
【发布时间】:2016-12-12 06:17:01
【问题描述】:

我有一个基类:

interface IBaseClass{
     int x;
     int y;
     baseClass someMethod();
}

还有一些派生类:

class dClass1 : IBaseClass {
     int x;
     int y;
     baseClass someMethod();
}
class dClass2 : IBaseClass {
     int x;
     int y;
     baseClass someMethod();
}

根据子类算法的属性值与其他子类不同 现在我想将这些子类转换为他们:

dClass1 c1=new dClass1 ();
c1.x=4;
c1.y=5;
dClass2 c2=c1;//cast to dClass2 , but value of property set by  according to the own algorithm  
Console.WriteLine("{0}, {1}", c1.x, c1.y);//4,5
Console.WriteLine("{0}, {1}", c2.x, c2.y);//7,1

【问题讨论】:

  • 你不能那样做。您可以将 dClass1 和 dClass2 都转换为 IBaseClass,因为两者都 IBaseClass。您不能将 dClass1 转换为 dClass2,因为 dClass1 不是 dClass2。我认为您对 C# 类的本质有一个错误的理解。
  • @EdPlunkett -- 它比“C# 类的本质”更广泛。它是面向对象编程的基本原则之一:多态性。
  • @roryap 好吧,我会在 C++98 中试一试(((dClass2 *)& c1),而不是dynamic_cast)(并不是说它是一个好主意,只是你可能会走运并为两者获得相同的布局),并且在 JavaScript 中它会非常有意义。我不是计算机科学家,我是一个指节狂。

标签: c# oop inheritance interface polymorphism


【解决方案1】:

dClass1dClass2两种不同的类型。您不能直接将一个转换为另一个。您必须将一个转换为另一个。例如:

dClass1 c1 = new dClass1
{
    x=4,
    y=5
};
dClass2 c2 = new dClass2
{
    x = c1.x,
    y = c1.y
};

或者,像原始代码一样使用多行:

dClass1 c1 = new dClass1();
c1.x=4;
c1.y=5;
dClass2 c2 = new dClass2();
c2.x = c1.x;
c2.y = c1.y;

关键是,系统无法直接将一种类型转换为另一种类型。您可以将此转换封装为任一类型或单独类的工厂方法。但铸造不是一种选择。仅仅因为这两种类型具有相同类型/名称/等的成员。不会使它们成为同一类型。

【讨论】:

    【解决方案2】:

    您尝试做的事情是不可能的。您可以将对象强制转换为更少(或在某些情况下更多)派生类型,但不能将对象强制转换为另一种类型,除非您在该类型上定义自定义强制类型转换。

    您可以在此处阅读有关定义自定义演员表的信息:https://msdn.microsoft.com/en-us/library/ms173105.aspx

    【讨论】:

      【解决方案3】:

      首先,让我们明确一点,IBaseClass不是一个基类,它是一个interface,这是完全不同的东西。指出差异不在此答案的范围内,但您可以从here 开始轻松阅读。

      也就是说,正如其他人所说,你不能直接做你想做的事。考虑典型示例IAnimalDogCat 等。每只狗和每只猫都是动物,但猫不是狗,狗也不是猫,你基本上是在要求猫成为狗;你首先需要教猫如何狗化(它们不会为你开箱即用)。

      为了实现这种行为,有很多方法可以做到:

      1. 用户定义转换:您可以定义从一个类转换为另一个类的运算符。如果您将它们设为implicit,您甚至可以按现在的方式编译代码:

        public static implicit operator dClass2(dClass1 obj)
        { //logic to convert obj to corresponding new dClass2 instance }
        

        现在这将是合法的:

        var c1 = new dClass1();
        dClass2 c2 = c1; // implicit cast operator is called.
        

        请注意,如果您要以显式方式实现强制转换运算符,则以前的代码将无法编译。您需要显式转换 c1:

        var c2 = (dClass2)c1;
        
      2. 定义一个带有dClass1 参数的dClass2 构造函数:

        public dClass2(dClass1 obj) { ... }
        

        你会编写以下代码:

        var c1 = new dClass1();
        var c2 = new dClass2(c1);
        
      3. dClass2 中定义一个静态工厂方法,它接受dClass1 参数并生成一个新的dClass2 实例:

        public static dClass2 CreateFrom(dClass1 obj) { ... }
        

        以及对应的代码:

        var c1 = new dClass1();
        var c2 = dClass2.CreateFrom(c1);
        
      4. 还有很多我懒得去想...

      你选择哪一个取决于个人喜好。我可能会使用显式强制转换,但任何可用选项本质上都没有错。

      【讨论】:

        最近更新 更多