如何在运行时期间使用派生类替换基类的实例

时间:2013-07-08 11:14:30

标签: c# inheritance replace instance-variables

我有一个简单的错误基类,为了这个问题的目的,一个int代表一个可能的错误值。

我从这个Error基类派生了一个ErrorMultiple类,它有一个int列表,这样我就可以保存多个错误值。

我希望将一个Event类包含在Error基类的单个实例中。

所以我创建了一个Event实例并将其传递给许多方法。其中一个决定“哦不。我们发现要报告多个错误。“

如何编写代码以使我的Event对象丢弃它的Error基类实例,并通过Event.ReplaceErrorObjWithMultipleErrorObj()将其替换为ErrorMultiple类的实例

public class Error
{
    protected int ErrorNo;
}
public class ErrorMultiple : Error
{
    Protected List<int> MultipleErrorNos;
}
public class Event
{
    Error   *   errorObject;
}

Public Event()
{
    errorObject = new Error();
}

void Event.ReplaceErrorObjWithMultipleErrorObj()
{
    errorObject = new ErrorMultiple();
}

当然,事件声明在真正的C#语法中是垃圾。我不知道如何声明对可替换对象实例的引用。

1 个答案:

答案 0 :(得分:1)

问题#01 - 价值类型和参考类型 在C ++中,对象是值类型 - 其组件的结构。要在存储器中生成值,请使用指针。 C#不是这样的。在C#中,默认情况下对象是引用,就对象而言,没有值类型。 (这使得这更简单有点谎言)

这意味着在C#中:

ErrorClass error = new ErrorClass();

在C ++中是等效的吗?

ErrorClass* error = new ErrorClass();

然而,关键的区别在于,无法取消引用C#引用,就像您可以在C ++中取消引用指针一样。

另外在C#:

error.ErrorNumber = 0;

在C ++中等同于此:

error->ErrorNumber = 0;

实际上正在发生的是,所有指针魔法都被隐藏在用户之外,以防止指针错误,并确保没有指针管理干扰托管语言的垃圾收集(一个系统在完成后删除对象) ,即它们超出范围)。

问题#02 - 语法 在C#中,编译器与C ++编译器有很大的不同。虽然缺少真正的定义和宏等功能,但它更智能,更不严格。

首先,类必须在一个块中完全包含它们的所有字段和方法,您不能声明类的基本结构并在之后声明事物的定义。即,你不能这样做:

class ErrorClass { public: void PrintError(); }
void ErrorClass::PrintError() { printf("error"); }

因为方法的定义必须在类的主体内部,所以:

class ErrorClass { public void PrintError() { Console.Write("error"); } }

但是,在使用函数之前,您不必声明函数的名称,编译器不一定按照函数的顺序读取代码。

为了总结一切,我将用适当的C#形式重写你的代码,这样你就可以看到事情的样子了:

public class Error
{
    protected int ErrorNo;
}
public class ErrorMultiple : Error
{
    protected List<int> MultipleErrorNos = new List<int>();
}
public class Event
{
    Error errorObject = new Error();
public void MultiplyErrors()
{
    errorObject = new ErrorMultiple();
}
}

请注意,首先,因为它们受到保护而无法读取错误号,其次C#有一个使用try,catch,finally和throw语句的基于异常的系统,类似于更现代的C ++。

建议阅读: