Type type
パラメータを一般的な引数と論理的に一致させることはできません< T >
。
拡張メソッドは非ジェネリックを返す必要がありIEnumerable
ます。
この構文IEnumerable
が実際に(実行時に)ジェネリックを保持するようにすることは可能ですIEnumerable < That particular type >
が、拡張メソッドを実行するユーザープログラマーは、仮定、チェック、および強制キャストを行う必要があります。
InvalidCastException
このルートをたどり、ユーザープログラマーが物事に気付いていない場合は、最終的になる可能性があることに注意してください:)。
ここに行きます:
public static class SomeExtensions {
private static readonly MethodInfo methodDefOf_PrivateHelper = typeof(SomeExtensions)
.GetMethod("PrivateHelper",
BindingFlags.NonPublic | BindingFlags.Static,
Type.DefaultBinder,
new [] { typeof(System.Collections.IEnumerable) },
null);
private static IEnumerable<T> PrivateHelper<T>(System.Collections.IEnumerable @this){
foreach (var @object in @this)
yield return (T)@object; // right here is were you can get the cast exception
}
public static System.Collections.IEnumerable DynamicCast(
this System.Collections.IEnumerable @this,
Type elementType
) {
MethodInfo particularizedMethod = SomeExtensions.methodDefOf_PrivateHelper
.MakeGenericMethod(elementType);
object result = particularizedMethod.Invoke(null, new object[] { @this });
return result as System.Collections.IEnumerable;
}
}
そして、これがあなたがそれを使うことができる方法です:
object[] someObjects = new object[] { "one", "two", "three" };
IEnumerable implicitlyCastedToEnumerable = someObjects;
Type unknownType = (DateTime.Now.Hour > 14) ? typeof(string) : typeof(int);
IEnumerable apparentlyNothingHappenedHere
= implicitlyCastedToEnumerable.DynamicCast(unknownType);
// if it's not after 14:00, then an exception would've jumped over this line and
// straight out the exit bracket or into some catch clause
// it it's after 14:00, then the apparentlyNothingHappenedHere enumerable can do this:
IEnumerable<string> asStrings = (IEnumerable<string>)apparentlyNothingHappenedHere;
// whereas the earlier would've cause a cast exception at runtime
IEnumerable<string> notGoingToHappen = (IEnumerable<string>)implicitlyCastedToEnumerable;