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
}