標籤:style color 使用 os strong io 資料 問題
一、定義介面
介面對一組方法簽名進行了統一命名。定義介面類型時,可指定的可見度為public 或 internal,但在[CLR via C#]第3版書中的原話是:"定義介面類型時,可指定你希望的任何可見度/可訪問性(public,protected,internal等)",個人認為這句話說得不妥。但無論如何,不嵌套在其他類型中的頂級類型的可訪問性只能是 internal 或 public。這些類型的預設可訪問性是 internal。
二、繼承介面
C#編譯器要求將用於實現一個介面的方法簡稱介面方法標記為public。CLR要求將介面方法標記為virtual。如果在原始碼中沒有顯式地將介面方法標記為virtual,編譯器會將它們標記為virtual和sealed;這會阻止衍生類別重寫介面方法。如果顯式地將介面方法標記為virtual,編譯器就會將此方法標記為virtual並保持它的非密封狀態,這樣一來,衍生類別就可以重寫它。
實值型別可以實現零個或多個介面。不過,將實值型別的執行個體轉型為介面類型時,實值型別的執行個體必須裝箱。這是由於介面變數是一個引用,它必須指向堆上的一個對象,使CLR能檢查對象的類型對象指標,從而判斷對象的確切類型。然後,在調用已裝箱實值型別的一個介面方法時,CLR會跟隨對象的類型對象指標,找到類型對象的方法表,從而調用正確的方法。
三、隱式和顯式介面方法實現
public class SimpleType : IDisposable
{
//隱式介面方法實現
public void Dispose(){ Console.WriteLine("public Dispose");}
//顯式介面方法實現(不允許指定可訪問性,但是編譯器產生方法的中繼資料時,其可訪問性會被自動設為private)
void IDisposable.Dispose(){Console.WriteLine("IDisposable Dispose")}
}
public static void Main()
{
SimpleType st = new SimpleType();
st.Dispose();//輸出結果為"public Dispose"
IDisposable d = st;
d.Dispose();//輸出結果為"IDisposable Dispose"
}
四、泛型介面
泛型介面提供的好處:
private void Method1()
{
Int32 x = 1, y = 2;
IComparable c = x;
c.CompareTo(y);//CompareTo期望接收一個Object類型的參數,傳遞y沒有問題,但是實值型別會裝箱
c.CompareTo("2")//可以編譯通過,但是在運行時會拋出異常,無法提供編譯時間型別安全
}
private void Method2()
{
Int32 x = 1, y = 2;
IComparable<Int32> c = x;
c.CompareTo(y);//CompareTo期望接收一個Int21類型的參數,傳遞y沒有問題,而且y不會裝箱
c.CompareTo("2")//編譯錯誤,可以提供編譯時間的類型檢查
}
1.泛型介面提供了出色的編譯時間型別安全。
2.處理實值型別時,裝箱次數會少得多。
3.類可以實現同一個介面若干次,只要每次使用不同的型別參數
五、在不存在泛型介面版本的情況下,怎樣實現來增強編譯時間的型別安全
public struct SomeValueType1 : IComparable
{
private Int32 _x;
public SomeValueType(Int32 x){ _x = x; }
public Int32 CompareTo(Object other)
{
return (_x - ((SomeValueType)other)._x);
}
}
public struct SomeValueType2 : IComparable
{
private Int32 _x;
public SomeValueType(Int32 x){ _x = x; }
public Int32 CompareTo(SomeValueType2 other)
{
return (_x - other._x);
}
Int32 IComparable.CompareTo(Object o)
{
return CompareTo((SomeValueTypes)o);
}
}
public static void Main()
{
SomeValueType1 v1 = new SomeValueType1(0);
Object o = new Object();
v1.CompareTo(v1); //實值型別進行裝箱操作
v1.CompareTo(o) //編譯通過,但運行時拋出InvalidCastException,沒法進行編譯時間型別安全的檢查
SomeValueType2 v2 = new SomeValueType2(0);
Object o = new Object();
v2.CompareTo(v2); //由於調用的是SomeValueType2自身聲明的方法,所以不用裝箱
v1.CompareTo(o) //無法通過編譯,能提供編譯時間的型別安全檢查
}