我有一个基类 CBase,我想要扩展它,所以从它派生出了 CDerived。
现在,某个程序从某个地方传了一个 CBase 的对象 baseObj 给我,由于我的所有处理逻辑都是以 CDerived 实现的,所以我想将 baseObj 转型成 CDerived类型:
CDerived derivedObj = (CDerived)baseObj;
这样编译是可以通过的,但是执行时会抛出异常,强制转换失败。
这个是C#的向下转型机制决定的,我明白……那么,我现在该怎么做呢?方案1:手动转换类型。
我给 CDerived 添加一个新的构造函数,允许传入一个 CBase 对象,通过这个对象的属性来调用基类的构造函数以构造新的对象。这样我可以得到一个新的 CDerived 对象,但是问题很明显,CBase 在构造函数中要求的很多参数我可能无法得到,更主要的,传入的 CBase 对象在通过这种方式转换为 CDerived 对象之后,对象内部的很多状态都会丢失。另外,转换后的对象和原有的 CBase 对象已经不是同一个对象了,这也是一个不大不小的问题。方案2:用extension。
我可以用extension来扩展CBase,这样就不需要派生CDerived类了。这样做很好很强大,但是当我需要从 CBase 派生第二个类 CDerivedAgain 时,我没办法再用这种方法了。除此之外,我想不到第三种方法了。特此求助。谢谢大家。

解决方案 »

  1.   

    1楼的老师,我可以重写所有逻辑,其中涉及到 CDerived 的地方都改用接口类型,但是 CBase 肯定没有实现我的接口,传 CBase 对象进去不可行啊。CBase 现在对于我来说是一个完全的黑盒,我能看到的只有元数据。
      

  2.   

    追加100分,第一个给出可行解决方案的老师独得200分。
    请在本帖回复。
    (加分贴地址:http://topic.csdn.net/u/20091120/16/d94479b9-7356-4a2c-b388-57d24f8b7173.html)
      

  3.   

    弄个接口让基类实现
    public class CBase:ICD
    然后
    CDerived derivedObj = (ICD)baseObj; 
      

  4.   

    5楼的老师,基类位于另一个dll中,除了它的元数据,我什么都拿不到。
      

  5.   

    既然不能用接口 那可以加个适配器 把所有需要用到的属性放入一个新类中 不要直接操作CDerived 
      

  6.   

    8楼的老师,我现在是身不由己 ~,~
    实际上,我在override某个类的一个方法,这个方法传入的参数就是CBase类型,由不得我改啊。
      

  7.   

    很简单啊,你在派生出的CDerived类中添加一个构造函数,传递基类对象,然后将基类需要的属性复制到当前类中不就好了吗?想想Stream系列的类,各个派生类之间的转换不都是这样实现的吗?
      

  8.   

    9楼和10楼的老师,虽然我可以得到objBase的public属性,但是protected和private的属性是无法得到的,因此新类的对象无法保持objBase的所有状态;更要命的是我必须将处理之后的objBase作为返回值返回。这个就是我说的第一种尝试方案。
      

  9.   

    @qldsrx 老师:这个我在“方案1”里面已经说了,新构建出的CDerived对象无法保持objBase的所有状态。
      

  10.   

    首先,父类转子类这种逻辑就违反OOP的原则,这个问题,从设计上就得改~ 
    搂主到底想干嘛? 
    CBase cderived = new CDerived();
    这样的写法不行吗,非要去new父类再转换,不明白什么情况
      

  11.   

    @tlzjff 老师:现在的情况是,我有某个类库里的一个类A,我派生之得到类B,从类B中override其基类的一个方法,该方法传入了一个CBase类的对象。这个类库对于我来说,除了全盘接受没有其他选择。背景就是这样。
      

  12.   

    CDerived作为一个独立类,不继承CBase,而将CBase对象传入
      

  13.   

    那你可以写一个CBaseHelper类吗,把CBase类里面的你要的东西都放到哪个类里面,然后写个函数返回的是CBaseHelper类,那个函数的参数就是CBase,所有的子类都继承自CBaseHelper而不是CBase,不知道我理解对了没
      

  14.   

    @ojlovecd 老师:你的方案跟yuxuanji老师的一样,有可行性,但是我在极力避免这么做,因此才来寻找更好的解决方法。CDerived,以及很多的平行类,在逻辑上绝对是CBase的派生类,不继承CBase,而是将它作为一个属性,不够和谐啊。
      

  15.   

    你的需求不要用继承了,@ojlovecd说的办法也不错
      

  16.   

    up
    Stream系列的类其实是装饰者模式的实现,动态给对象添加特性
      

  17.   

    可以考虑这种体系
     public class p
        {
            static void Main(string[] args)
            {
                CBase baseObj = new CBase();            CDerived derivedObj = new CDerived(baseObj);            derivedObj.Test();
                           Console.Read();
            }
        }
        public interface IC
        {
            void Test();
        }    public class CBase:IC
        {
                    public void Test()
            {
                Console.WriteLine("CBase Test");
            }      
        }    public class CDerived  : CBase
        {
            IC _cbase;
            public CDerived()
            { }
            //通过构造函数包装实现IC类对象
            public CDerived(IC a)
            {
                this._cbase = a;
            }                public new void Test()
            {
                Console.WriteLine("Bcc Test");
            }       
        }
      

  18.   

    可以考虑一下装饰者模式。
    在不改变具体类的情况下对该类进行扩展public class CBase
    {
         public int Plus(int a,int b)
         {
             return a+b;
         }
    }public class CBaseStringChanger:CBase
    {
        private CBase obj;
        public ExtBase(CBase base)
        {
             this.Obj=base;
        }
        
        public string PlusToString(int a,int b)
        {
            return Convert.ToString(this.Obj.Plus(a,b));
        }    
    }public class CBaseDoubleChanger:CBase
    {
        private CBase obj;
        public ExtBase(CBase base)
        {
             this.Obj=base;
        }
        
        public string PlusToDouble(int a,int b)
        {
            return Convert.ToDouble(this.Obj.Plus(a,b));
        }    
    }
      

  19.   

    谢谢各位老师。所以总之,我只能用把CBase作为CDerived的属性的方法来实现了?我真的不喜欢这种方式……
      

  20.   

    各位老师大家好,经过NNNN久的研究,终于找到了一个很好的解决方法。我再把问题和问题所处的环境描述一下。
    有一个类库,其中有A类和B类,A类中有一个方法X要求传入一个B类对象,处理后将之返回。
    在我的代码中,我从A类派生了a类,B类派生了b类。在覆写A类的X方法时,传入一个b类对象,就出现了在主贴中所说的问题。解决方法……很惭愧,我在A类中找到了另一个方法Y,返回一个B类对象。X方法要求传入的B类对象,恰恰是通过这个Y方法获得的。因此,我只要简单地覆写Y方法,返回一个b类对象就可以了。因为如果一个B类对象本身就是一个b类对象,那么向下转换是可行的。感谢大家,这贴先结了,下面这贴就当散分,大家去占位吧。两天后结贴。
    http://topic.csdn.net/u/20091120/16/d94479b9-7356-4a2c-b388-57d24f8b7173.html