将基类型转换/转换为派生类型

时间:2010-03-25 21:24:24

标签: c# .net

我通过派生来扩展现有的.NET框架类。如何将基类型的对象转换为派生类型?

public class Results { //Framework methods }

public class MyResults : Results { //Nothing here }

//I call the framework method

public static MyResults GetResults()
{
    Results results = new Results();
    //Results results = new MyResults(); //tried this as well.

    results = CallFrameworkMethod();

    return (MyResults)results; //Throws runtime exception
}

我理解这种情况发生在我尝试将基类型转换为派生类型时,如果派生类型具有其他属性,则不会分配内存。当我添加其他属性时,我不在乎它们是否被初始化为null。

如果不进行手动复制,我该怎么做?

6 个答案:

答案 0 :(得分:11)

你做不到。如果results未引用MyResults(例如,如果CallFrameworkMethod返回基本Results实例),则转换将不会如此:您需要根据现有的非MyResults创建新的MyResults。转换是关于更改引用的编译时类型,而不是更改引用对象的具体类型。

您可以使用Reflection或AutoMapper等工具来帮助初始化新的MyResults对象 - 但必须有一个新的MyResults对象,因为您无法告诉基础{{1 object成为Results对象。

答案 1 :(得分:1)

怎么样:

...
MyResults results  = new MyResults();
...

您可能还需要在MyResults类中创建一个COnstructor:

public class MyResults : Results
{
    public MyResults() : base() {}
}

<击> 究竟什么意思“什么都没有”?

编辑

 results = (CallFrameworkMethod() as MyResults);

它不会抛出异常,但如果它对你有用 - 这取决于你想要做的事情......

答案 2 :(得分:1)

不,您无法避免将内容复制到派生类型的实例中。好吧,如果您可以将CallFrameworkMethod更改为通用方法,并且MyResults具有零参数构造函数,则CallFrameworkMethod可以直接创建派生类型的新实例,然后仅使用父类型的成员。

但是你可能不得不最终复制到一个新对象。请记住,这个复制代码当然可以在另一个方法中重用,您无需在任何需要的地方重写它。

答案 3 :(得分:1)

如前面的答案所述,您需要实例化MyResults的新实例,然后从Results对象复制属性。你问了什么是“复制构造函数” - 它只是一个构造函数,它接受一个对象并使用它来填充正在构造的对象。例如:

    public class Results
    {
        public string SampleProperty1 { get; set; }
        public string SampleProperty2 { get; set; }
    }

    public class MyResults : Results
    {
        public MyResults(Results results)
        {
            SampleProperty1 = results.SampleProperty1;
            SampleProperty2 = results.SampleProperty2;
        }
    }

复制构造函数通常比使用这样的代码更方便,可读和可重用:

MyResults myResults = new MyResults
{
    SampleProperty1 = results.SampleProperty1,
    SampleProperty2 = results.SampleProperty2
};

如果有很多属性和/或您对该类进行了大量更改,则可以使用反射(例如C# Using Reflection to copy base class properties)或AutoMapper(http://automapper.codeplex.com等工具)来复制属性。但通常这可能是矫枉过正的。

答案 4 :(得分:0)

Results results = new MyResults();
   ...

return (MyResults)results;

应该有效。如果没有,那么问题就在某处。

答案 5 :(得分:0)

要将对象向下转换为其派生类,对象必须出生在其派生类中。 例如: 我有一个简单的类叫做 Shape 这是Shape类的代码

public class Shape{
     public void draw(){}
}

然后我还有一个名为 Circle 的类,如下所示:

public class Circle:Shape{
      public void drawCircle(){}
}

现在如果我创建一个像超级类的对象

Shape noShape = new Shape();

如果尝试像这样将这个 noShape 对象向下转换为 Circle 对象

Circle circle = (Circle) noShape; 

它会产生一个异常。这是因为 circle 从未出生成为Shape 要执行此向下转换功能,noShape 必须出生作为 Circle 对象。可以这样做:

Circle initialShape = new Circle();

现在您可以简单地将此 initialShape 对象向上转换为 Shape 对象。像这样

Shape upcastedObject = initialShape;

现在您可以将对象 upcastedObject 向下转换为其派生类,如

Circle derivedCircle = (Circle) upcastedObject;

现在 derivedCircle 对象的行为类似于 Circle 对象。因为它诞生于Circle。我使用的是 BORN 这个词,所以请记住这一点。 这样做的原因或这样做的用例取决于您的要求。