new int(3)
// x2 is a reference to a value on the heap但是,在
C#中,你就无法控制: int x1 = 3; // x1 is a value on the stack
int x2 = new int();
x2 = 3; // x2 is also a value on the stack!
2.5 也就是说,int是值类型,object是引用类型。那么,int又怎么能从object派生出来呢? 其实,
int并不是从object派生出来的。当一个int数被作为int数使用时,它就是一个值类型实例(保存在栈上)。但是,当它被作为object派生对象使用时,它就是一个引用类型实例,指向堆上的一个整数值。换句话说,当你把int值作为对象来对待时,运行时会自动地将int值转换成一个object引用。这个过程就被称为装箱(boxing)。这个转换的过程包括如下步骤:将int值的内容从栈拷贝到堆,然后创建一个object实例来指向它。解箱(unboxing)则是装箱的逆过程:将对象转换回栈上的值。 int x = 3; // new int value 3 on the stack
object objx = x; // new int on heap, set to value 3 - still have x=3 on stack
int y = (int)objx; // new value 3 on stack, still got x=3 on stack and objx=3 on heap
2.6 C#用引用代替了指针。C#的引用和C++的引用是一样的吗? 并不完全一样。它们的基本思想是一样的,但是一个明显的差异是:
C#的引用可以为null。因此,你不能期望C#引用始终指向合法的对象。如果你尝试使用一个为null的引用,系统就会抛出一个NullReferenceException异常。 例如,请看下列方法:
void displayStringLength( string s )
{
Console.WriteLine( "String is length {0}", s.Length );
}
这个方法的问题在于:如果你像下面这样调用它,它就可能抛出一个
NullReferenceException异常。 string s = null;
displayStringLength( s );
当然,在某些情况下,你可能会认为
NullReferenceException是一个完全可以接受的调用结果。但是,在这里,最好是将这个方法改写为下面这样: void displayStringLength( string s )
{
if( s == null )
Console.WriteLine( "String is null" );
else
Console.WriteLine( "String is length {0}", s.Length );
}
3. 类和结构体 3.1 在C++中,结构体基本上是多余的东西。为什么C#中还要有结构体呢? 在
C++中,结构体和类基本上是完全一样的,它们唯一的区别就在于默认的可见程度(结构体的默认可见程度是public,类的默认可见程度是private)。但是,在C#中,结构体和类有着非常大的差异。在C#中,结构体是值类型(保存在栈上),而类则是引用类型(保存在堆上)。另外,结构体不能继承结构体或者类,只能实现接口。结构体也没有析构子(destructor)。 3.2 C#支持多继承吗? C