2

与えられた

        int foo = 1;
        Type unboundType = typeof(List<>);
        Type w = unboundType.MakeGenericType(typeof(int));

        if (w == typeof(List<int>))
        {
            Console.WriteLine("Yes its a List<int>");

            try
            {
                ((List<int>)(object)w).Add(foo);
            }
            catch(InvalidCastException)
            {
                Console.WriteLine("No you can't cast Type");
            }
        }   

タイプが実際に構築されたタイプと一致することを確認し、その構築されたタイプに基づいてアクションを実行できます。ただし、使用中または明示的なキャストにキャストTypeすることはできません。開発者がバインドされていない型を作成できるようにする実用的な目的はありますか?それとも、この機能は何らかの方法で言語をサポートするためだけに存在しますか?classasType

4

3 に答える 3

4

投稿したコードでは、実際にはそのタイプのオブジェクトをどこにもインスタンス化しませんでした。System.TypeのインスタンスをキャストしようとしているだけでList<int>、意味がありません。コードを更新して実際にインスタンスを作成すると、次のように機能します。

int foo = 1;
Type unboundType = typeof(List<>);
Type w = unboundType.MakeGenericType(typeof(int));

if (w == typeof(List<int>))
{
    Console.WriteLine("Yes its a List<int>");
    object obj = Activator.CreateInstance(w);

    try
    {
        ((List<int>)obj).Add(foo);
        Console.WriteLine("Success!");
    }
    catch(InvalidCastException)
    {
        Console.WriteLine("No you can't cast Type");
    }
}

多分私はあなたの質問の要点を見逃しているだけです。確かにロジックによっては、コンパイル時にわからないタイプに基づいて if/else チェックを行うことができます (この例では、 で作業していることはわかっintていますが、実行時には必要に応じて他のタイプになる可能性があります) 。

編集:真のランタイム使用例を提供するために、次のことを考慮してください。

public object CreateList(Type elementType, object initialValue)
{
    if (!elementType.IsAssignableFrom(initialValue.GetType()))
        throw new ArgumentException("Incompatible types!");

    Type unboundType = typeof(List<>);
    Type listType = unboundType.MakeGenericType(elementType);
    object list = Activator.CreateInstance(listType);
    var addMethod = listType.GetMethod("Add");
    addMethod.Invoke(list, new []{initialValue});
    return list;
}

これによりList<T>、実行時に不明なタイプ/オブジェクトから を作成できます。いくつかの使用法:

object intList = CreateList(typeof(int), 1);
object stringList = CreateList(typeof(string), "asdf");

object objectFromSomewhere = GetMyUnknownObject();
object someUnknownListType = CreateList(objectFromSomewhere.GetType(), objectFromSomewhere);

そのため、オブジェクトをそのままでは多くのことができない場合があります。IEnumerableおそらく少なくともそれらを扱うことができたでしょう。しかし、それはあなたのシステムが何をする必要があるか次第です。

IList編集:インターフェースを忘れました:

public IList CreateList(Type elementType, object initialValue)
{
    if (!elementType.IsAssignableFrom(initialValue.GetType()))
        throw new ArgumentException("Incompatible types!");

    Type unboundType = typeof(List<>);
    Type listType = unboundType.MakeGenericType(elementType);
    IList list = (IList)Activator.CreateInstance(listType);
    list.Add(initialValue);
    return list;
}
于 2013-02-01T19:50:51.333 に答える
4

コンパイル時にすべてを実行できるわけではありません。特にライブラリ コードでは、与えられたものを受け取る必要がある場合があります。objectまたはのみが与えられ、巧妙な処理を行う必要があるシナリオではType、バインドされていない型が非常に役立ちます。例えば:

object obj = NoIdeaWhatThisReturns();
IList list = (IList)Activator.CreateInstance(
                 typeof(List<>).MakeGenericType(obj.GetType()));
list.Add(obj);

基本的; 多くのリフレクションまたはメタプログラミングを使用するシナリオでは、おそらくある時点でバインドされていない型を使用していることに気付くでしょう。

于 2013-02-01T19:57:34.377 に答える
0

Type特定の型のプレースホルダーではありません。他の型を記述するのは、それ自体が特定の型です。メタデータは(明らかに)その特定の型に対して機能できないため、関連のない別の型にキャストしようとしても意味がありません。

メタデータ型は、特定の型を作成するためではなく、さまざまな側面を検査するために使用されます。一般的な方法で型のインスタンスを作成したい場合は、Activatorそのためにクラスを使用できます。

Type oType = ...; // get a Type instance here about a type
object[] oArgs = { oParam1, oParam2 }; // constructor parameters (if any)

return ( Activator.CreateInstance ( oType, oArgs ) );

これにより、たとえば、文字列に基づいて型を作成できます。TypeのインスタンスをSystem.String(または のような関数呼び出しから)取得し、GetTypeNameFromUser(...)その型のインスタンスを作成できます。(Activator文字列を取得するための直接サポートがありますが、内部的には、Typeインスタンス化する必要がある型を検索するために使用します。)

すべての型が等しいTypeため、バインドされていないジェネリック型のインスタンスを他の型と同じように作成できます。少なくとも、そのプロパティとメソッドを調べることができます。(受け入れられた回答が示すように、Typeインスタンスを使用して、を使用して特殊なジェネリック型を作成することもできますMakeGenericType。)

于 2013-02-01T19:55:39.343 に答える