這個做法在說明泛型方法的限制與能夠利用 dynamic
動態類型來彌補這些限制。
首先先看一下這段程式碼,MyType
類別建立了隱含轉換,正常運作下能夠把 string 轉換成 MyType 的 StringMember
,
但實際上會直接拋出 InvalidCastException
。
void Main()
{
var answer1 = GetSomeStrings().Cast<MyType>();
try
{
foreach (var v in answer1)
Console.WriteLine(v);
}
catch (InvalidCastException)
{
Console.WriteLine("Cast Failed!");
}
}
public class MyType
{
public string StringMember { get; set; }
public static implicit operator string(MyType aString) => aString.StringMember;
public static implicit operator MyType(string aString) => new MyType { StringMember = aString };
}
public static string[] GetSomeStrings()
{
return new string[] { "Hello, ", "World!" };
}
這是因為 Cast
當然我們可以直接跳過轉型的操作,直接使用建構函式建立新的物件。
void Main()
{
var answer4 = GetSomeStrings().Select(n => new MyType { StringMember = n });
var answer5 = from v in GetSomeStrings()
select new MyType { StringMember = v };
}
也可以使用 dynamic
讓型別轉換在執行時期解決,而不是編譯時期,這行程式碼能夠在執行時期將 item 轉換回 string,之後
MyType 的隱含轉換就能生效了。
public static IEnumerable<TResult> Convert<TResult>(this IEnumerable sequence)
{
foreach (object item in sequence)
{
dynamic coercion = (dynamic)item;
yield return (TResult)coercion;
}
}
使用上的效果跟下面相同,就是要確認 item 的真實型別。
var convertedSequence = GetSomeStrings();
foreach (string item in convertedSequence)
{
Console.WriteLine((MyType)item);
}
Summary
這個做法說明了 Castdynamic
在執行期別
把轉型缺失的資訊補上,可以彌補 Cast