C Sharp/Objects
System.Object
编辑对象默认继承自System.Object
, 也称作Object
或object
。其方法有:
GetHashCode()
- 获取对象的独一无二IdGetType()
-ToString()
-
对象
编辑对象默认是引用类型。如果想支持值类型,就必须从System.ValueType
抽象类派生。
构造函数
编辑构造函数通常为public。 构造函数没有返回类型(即使void也不行)。使用new关键字创建一个类的实例时,调用构造函数。
拷贝构造函数
编辑using System;
namespace CopyConstructor
{
class Rectangle
{
public int length;
public int breadth;
public Rectangle(int x, int y) // constructor fn
{
length = x;
breadth = y;
}
public Rectangle(Rectangle r)
{
length = r.length;
breadth = r.breadth;
}
public void display()
{
Console.WriteLine("Length = " + length);
Console.WriteLine("Breadth = " + breadth);
}
} // end of class Rectangle
class Program
{
public static void Main()
{
Rectangle r1 = new Rectangle(5, 10);
Console.WriteLine("Values of first object");
r1.display();
Rectangle r2 = new Rectangle(r1);
Console.WriteLine("Values of second object");
r2.display();
Console.ReadLine();
}
}
}
静态构造函数
编辑当运行时第一次访问一个类时,该类的静态构造函数被调用(且仅此一次),给类的静态数据成员赋值。
静态构造函数必须无参。只能有一个静态构造函数。
using System;
using System.Collections.Generic;
using System.Text;
namespace StaticConstructors
{
class Program
{
static void Main(string[] args)
{
int i = 0;
int j = 0;
Console.WriteLine("Static Number = " + MyClass.Number);
}
}
class MyClass
{
private static int _number;
public static int Number { get { return _number; } }
static MyClass()
{
Random r = new Random();
_number = r.Next();
}
}
}
缺省构造函数
编辑缺省构造函数是无参的、隐式定义(如果没有显式定义任何构造函数)。
// Created by the developer
class MyClass
{
}
// Created by the compiler
class MyClass : System.Object
{
public MyClass() : base()
{
}
}
重载构造函数
编辑 class MyClass
{
private int _number;
public int Number { get { return _number; } }
public MyClass()
{
Random randomNumber = new Random();
_number = randomNumber.Next();
}
public MyClass(int seed)
{
Random randomNumber = new Random(seed);
_number = randomNumber.Next();
}
}
调用其他构造函数
编辑可以让一个构造函数去调用另一个构造函数:
class MyClass
{
private int _number;
public int Number { get { return _number; } }
public MyClass() :
this ( DateTime.Now.Milliseconds ) // Call the other constructor passing in a value.
{
}
public MyClass(int seed)
{
Random r = new Random(seed);
_number = r.Next();
}
}
也可以调用基类的构造函数:
class MyException : Exception
{
private int _number;
public int Number { get { return _number; } }
public MyException ( int errorNumber, string message, Exception innerException)
: base( message, innerException )
{
_number = errorNumber;
}
}
析构函数和Dispose方法
编辑析构函数直到垃圾回收时才被调用。所以考虑适用Dispose()
方法。
资源类型分为:
- 托管资源:由CLR创建和释放
- 非托管资源:资源的创建和释放不由CLR管理。比如IO、网络连接、数据库连接等等。需要开发人员手动释放。
终结器(Finalizer)是GC允许对象被摧毁前清理非受管的资源的方法。但GC不保证终结器一定会被调用、调用的次序(如一个对象引用另一个对象,这两个对象的终结器的执行次序)。不能显式调用或覆盖终结器,它是编译器根据析构函数隐式生成,由GC隐式调用。终结器总是protected而非公有或私有。终结器应该只释放非受管资源(受管资源随后由GC清理)。不要在终结器中分配内存、调用虚函数、抛出未处理的异常。不要给值类型定义终结器(因为它不会被GC调用)。不要创建空的析构函数。
class Test
{
// Some Code
~Test
{
//Necessary cleanup code
}
}
//将被自动编译为:
protected override void Finalize()
{
try
{
//Necessary cleanup code
}
finally
{
base.Finalize();
}
}
类库会提供释放的方法,即约定为Dispose,调用即可。有非受管资源需要清理释放,应该显式调用Dispose方法。反之,如果一个类有Dispose方法清理受管资源,则程序就应该显式调用Dispose方法而不应该等待GC调用终结器。这样的类应该实现IDisposable接口和the Dispose方法。最佳实践建议同时实现Dispose方法和析构函数,显式调用Dispose释放非受管资源,GC调用终结器可处理编程者忽略调用Dispose的情形。如果有析构函数,就应该实现IDisposable。应考虑Dispose被调用多次的可能。对值类型不应写Dispose方法。Dispose方法中不应该抛出异常。
public class Base: IDisposable
{
private bool isDisposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); //要求runtime不要再调用这个终结器了。因为重复释放非受管资源会造成不可控后果。
}
protected virtual void Dispose(bool disposing)
{
if(!isDisposed)
{
if (disposing)
{
// Code to dispose managed resources
// held by the class
}
}
// Code to dispose unmanaged resources
// held by the class
isDisposed = true;
base.Dispose(disposing);
}
~Base()
{
Dispose (false);
}
}
public class Derived: Base
{
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Code to cleanup managed resources held by the class.
}
// Code to cleanup unmanaged resources held by the class.
base.Dispose(disposing);
}
// Note that the derived class does not // re-implement IDisposable
}