我們宣告了三個類別 ClassA 是最上層的基底類別,Class B 則是繼承了 ClassA,ClassC 繼承了 ClassC。
ClassA -> ClassB -> ClasssC
這三個類別,都有分別覆寫 ToString 這個方法,他們的建立程式碼如下所示。
class ClassA : ICloneable
{
public object Clone()
{
return this.MemberwiseClone();
}
public override string ToString()
{
return "It is ClassA";
}
}
class ClassB : ClassA
{
public override string ToString()
{
return "It is ClassB";
}
}
class ClassC : ClassB
{
public override string ToString()
{
return "It is ClassC";
}
}
as 的用法
從微軟官方的說明文件中,我們可以知道
使用 as 運算子,以在相容的參考型別或可為 Null 的型別之間執行特定轉換類型
在這裡,我們建立起六個物件,分別指定到型別為 object 的陣列中。
接著,我們使用 as 運算子,將執行時期的物件型別,強制轉型成為 string 這個型別,若當時物件的實際產生的型別不是 string,則,轉型出來的內容將會是空值 null。
object[] objArray = new object[6];
objArray[0] = new ClassA();
objArray[1] = new ClassB();
objArray[2] = "hello";
objArray[3] = 123;
objArray[4] = 123.4;
objArray[5] = null;
for (int i = 0; i < objArray.Length; ++i)
{
// 在這裡進行型別轉換
string s = objArray[i] as string;
Console.Write("{0}:", i);
if (s != null)
{
Console.WriteLine("'" + s + "'");
}
else
{
Console.WriteLine("not a string");
}
}
底下是輸出結果
0:not a string
1:not a string
2:'hello'
3:not a string
4:not a string
5:not a string
Press any key for continuing...
is 的用法
從微軟官方的說明文件中,我們可以知道
is 運算子用於檢查物件是否與指定的類型相容
在這裡,我們分別建立 ClassA, ClassB, ClassC 這個三型別物件,在這三個物件,接著使用 is 運算子來檢驗是否與我們指定的型別運算之後,回得到 true 的回傳值。
在這裡,我們看到了,只要執行時期所產生的物件搭配 is 運算子運算之後,只要檢驗的型別,是當時物件的型別、繼承的型別、有繼承的介面,驗證結果皆會為真。
var cl1 = new ClassA();
Console.WriteLine($"cl1 is IFormatProvider : {cl1 is IFormatProvider}");
Console.WriteLine($"cl1 is ICloneable : {cl1 is ICloneable}");
Console.WriteLine($"cl1 is Object : {cl1 is Object}");
Console.WriteLine($"cl1 is ClassA : {cl1 is ClassA}");
Console.WriteLine($"cl1 is ClassB : {cl1 is ClassB}");
Console.WriteLine($"cl1 is ClassC : {cl1 is ClassC}");
Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
Console.ReadKey();
var cl2 = new ClassB();
Console.WriteLine($"cl2 is IFormatProvider : {cl2 is IFormatProvider}");
Console.WriteLine($"cl2 is ICloneable : {cl2 is ICloneable}");
Console.WriteLine($"cl2 is Object : {cl2 is Object}");
Console.WriteLine($"cl2 is ClassA : {cl2 is ClassA}");
Console.WriteLine($"cl2 is ClassB : {cl2 is ClassB}");
Console.WriteLine($"cl2 is ClassC : {cl2 is ClassC}");
Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
Console.ReadKey();
var cl3 = new ClassC();
Console.WriteLine($"cl3 is IFormatProvider : {cl3 is IFormatProvider}");
Console.WriteLine($"cl3 is ICloneable : {cl3 is ICloneable}");
Console.WriteLine($"cl3 is Object : {cl3 is Object}");
Console.WriteLine($"cl3 is ClassA : {cl3 is ClassA}");
Console.WriteLine($"cl3 is ClassB : {cl3 is ClassB}");
Console.WriteLine($"cl3 is ClassC : {cl3 is ClassC}");
Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
Console.ReadKey();
底下是輸出結果
cl1 is IFormatProvider : False
cl1 is ICloneable : True
cl1 is Object : True
cl1 is ClassA : True
cl1 is ClassB : False
cl1 is ClassC : False
Press any key for continuing...
cl2 is IFormatProvider : False
cl2 is ICloneable : True
cl2 is Object : True
cl2 is ClassA : True
cl2 is ClassB : True
cl2 is ClassC : False
Press any key for continuing...
cl3 is IFormatProvider : False
cl3 is ICloneable : True
cl3 is Object : True
cl3 is ClassA : True
cl3 is ClassB : True
cl3 is ClassC : True
Press any key for continuing...
我們在進行另外一個測試,那就是若產生的物件為一個衍生型別,而宣告的持有物件變數的型別為基底型別,這樣使用 is 運算子的結果會如何呢?
從底下的執行結果輸出內容可以清楚的觀察到, is 運算子會使用執行時期實際產生的物件型別,來進行型別檢驗。
Console.WriteLine($"ClassA clxl = cl2;");
ClassA clx1 = cl2;
Console.WriteLine($"ClassB clx2 = cl3;");
ClassB clx2 = cl3;
Console.WriteLine($"ClassA clx3 = cl3;");
ClassA clx3 = cl3;
Console.WriteLine($"{Environment.NewLine}");
Console.WriteLine($"clx1 is ClassA : {clx1 is ClassA}");
Console.WriteLine($"clx1 is ClassB : {clx1 is ClassB}");
Console.WriteLine($"clx1 is ClassC : {clx1 is ClassC}");
Console.WriteLine($"clx2 is ClassA : {clx2 is ClassA}");
Console.WriteLine($"clx2 is ClassB : {clx2 is ClassB}");
Console.WriteLine($"clx2 is ClassC : {clx2 is ClassC}");
Console.WriteLine($"clx3 is ClassA : {clx3 is ClassA}");
Console.WriteLine($"clx3 is ClassB : {clx3 is ClassB}");
Console.WriteLine($"clx3 is ClassC : {clx3 is ClassC}");
Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
Console.ReadKey();
底下是輸出結果
ClassA clxl = cl2;
ClassB clx2 = cl3;
ClassA clx3 = cl3;
clx1 is ClassA : True
clx1 is ClassB : True
clx1 is ClassC : False
clx2 is ClassA : True
clx2 is ClassB : True
clx2 is ClassC : True
clx3 is ClassA : True
clx3 is ClassB : True
clx3 is ClassC : True
Press any key for continuing...
類型模式執行模式比對
從微軟的官方文件中,可以得到
從 C# 7 開始,您可以搭配類型模式使用模式比對來撰寫更簡潔的程式碼,以使用 is 陳述式。
我們在這裡來使用看看,他的用法如下:
expr is type varname
例如,在底下的測試程式碼中,使用的
MyTest is ClassC e1
就是這樣的用法;若使用類型模式執行模式比對得到為否,e1 這個變數便會為空值 null。var cl1 = new ClassA();
var cl2 = new ClassB();
var cl3 = new ClassC();
object MyTest;
// 用類型模式執行模式比對時,is 會測試運算式是否可轉換成指定的類型;如果可以的話,則會將它轉換成該類型的變數。 它是 is 陳述式的直接延伸,允許精簡類型的評估和轉換。
// https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/is#type
MyTest = cl2;
if (MyTest is ClassC e1)
{
Console.WriteLine($"cl2 is ClassC : {e1.ToString()}");
}
if (MyTest is ClassA e2)
{
Console.WriteLine($"cl2 is ClassA : {e2.ToString()}");
}
Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
Console.ReadKey();
底下是輸出結果
cl2 is ClassA : It is ClassB
Press any key for continuing...
Press any key for continuing...