#支持对接口的多继承,但是不支持对类的多继承。每个类最多只能继承一个类,但可以实现多个接口。
3.3 C#中的接口和C++中的抽象类是一样的吗? 不完全一样。
C++中的抽象类不能实例化,但可以(并且经常的确)含有实现代码和/或数据成员;C#中的接口则不能含有任何实现代码或者数据成员,它只是一组方法名称和签名的集合。比起C++中的抽象类,C#中的接口跟COM中的接口更相似。 这两者之间另一个重要的区别是:
C#的类只能继承一个类(不论是不是抽象的),但可以实现多个接口。 3.4 C#中的构造子和C++中的构造子是一样的吗? 非常相似。
3.5 C#中的析构子和C++中的析构子是一样的吗? 不!它们看上去差不多,但是实际上完全不同。首先,
C#不保证在任何特定的时间点调用析构子,甚至不保证析构子会被调用。说实话,C#中的析构子其实就是Finalize方法,只不过换了个说法而已。或者说,它是一个会调用基类Finalize方法的Finalize方法。因此,下列代码: class CTest
{
~CTest()
{
System.Console.WriteLine( "Bye bye" );
}
}
实际上就是:
class CTest
{
protected override void Finalize()
{
System.Console.WriteLine( "Bye bye" );
base.Finalize();
}
}
从
.NET框架Beta 2开始,程序员不能再像这样显式覆盖Finalize方法——你必须使用析构子语法。 3.6 既然C#中的析构子和C++中的析构子有这么大的差异,为什么微软还要使用一样的语法呢? 因为微软的人是坏蛋,他们想把你的脑子弄得一团糟。
3.7 什么是静态构造子? 所谓静态构造子(
static constructor)就是为一个类(而不是类的实例)准备的构造子。当一个类被装载的时候,这个类的静态构造子就会被调用。 3.8 C#中所有的方法都是虚拟的吗? 不。和
C++一样,方法默认是非虚拟(non-virtual)的,但你可以将它们标记为虚拟(virtual)方法。 3.9 在C#中如何声明纯虚函数? 用
abstract关键字来修饰一个方法,就可以将这个方法声明为纯虚的。自然,这个方法所属的类也必须同时被标记为抽象类。请注意,抽象方法不能有任何实现代码(这跟C++中的纯虚函数也有所不同)。 4. 异常 4.1 在C#中可以使用异常吗? 可以。实际上,在
C#(以及整个.NET环境)中,异常是被推荐的错误处理机制。大多数.NET框架类都使用异常来表示错误。 4.2 哪些类型的对象可以作为异常抛出? 只有
System.Exception类及其派生类的实例可以作为异常抛出。这和C++形成了鲜明的对比——在C++中,几乎任何类型的实例都可以作为异常抛出。 4.3 我可以定义自己的异常吗? 可以,只要让你的异常类继承
System.Exception类就行了。更明确一点,微软推荐用户定义的异常继承System.ApplicationException类(这个类继承了System.Exception类)。 4.4 C#中有没有可以复用的标准异常? 有,其中的一些异常和标准的
COM HRESULT值有一定的关系。下表展示了HRESULT和.NET(以及C#)异常的对应关系: HRESULT | .NET异常 |
E_INVALIDARG | ArgumentOutOfRangeException,或者更普通的ArgumentException。如果提供的参数格式不对(例如URL以“htp://”开头,而不是以“http://”开头),可以选择使用FormatException。 |
E_POINTER | ArgumentNullException |
E_NOTIMPL | NotImplementedException |
E_UNEXPECTED | 通常认为InvalidOperationException是与之相对应的。InvalidOperationException通常被用于表示“对象无法执行所请求的操作”。 |
E_OUTOFMEMORY | OutOfMemoryException |
其