1

多分それはかなり単純ですが、私はその型Typeとその用途に慣れていません。

関数の結果に応じて、=または=のList<T>いずれかを作成したいとします。TDoubleTUInt32public static Type CheckType(String input);

コード内:

Type t = Program.CheckType(someInput); // it returns typeof(Double) or typeof(UInt32)
if (t == typeof(Double))
    List<Double> l = new List<Double>();
else
    List<UInt32> l = new List<UInt32>();

l2つの異なる意味(doubleのリストとunsigned intのリスト)を許可しているため、上記のコードがコンパイルされないことはわかっています...だから、私の質問につながります:

  • if上記のコードを回避する方法はありますか?

これに似たもの:

Type t = Program.CheckType(someInput);
List<t> l = new List<t>(); // I know this won't compile either...

つまり、一般的なリストを一般的にインスタンス化します...

前もって感謝します!

編集:

これは、マークされた質問の複製ではありません。理由は 1 つだけです。匿名タイプではありません。ここでの問題は、入力データの型(たとえば、=または= ) を決定し、その入力データ型に基づいてジェネリックを作成する方法です。DoubleUInt32Type Ttypeof(Double)Type Ttypeof(UInt32) SampleClass<T> T

つまり、実行時に someType Tを決定し、決定された type でジェネリック型をインスタンス化しますT。前にそれを明確にしなかった場合は申し訳ありません...

PS:List<T>の例として使用しましたSampleClass<T>

4

5 に答える 5

6

型パラメーターがわからないため、リストをジェネリックとして型指定することはできませんが、実行時に List インスタンスを作成することはできます。

Type t = Program.CheckType(someInput);
Type listType = typeof(List<>).MakeGenericType(t);
IList list = (IList) Activator.CreateInstance(listType);

間違ったタイプのオブジェクトを追加しようとすると、例外が発生するため、このアプローチには、のようなコレクションを使用するよりも利点がありますArrayListList<object>

于 2013-02-05T20:37:39.143 に答える
2

私はジェネリックに行きHistogram<T>ますが、変数だけが必要でない限り、両方の型を同じ変数に保持しようとはしませんIDictionary

double以下は、型のあるヒストグラムを使用した例です。

class Program
{

    static Random rnd=new Random();
    static void Main(string[] args)
    {
        Historgram<double> hist=new Historgram<double>();
        for(int i=0; i<1000; i++)
        {
            double x=Math.Round(rnd.NextDouble(), 1);
            hist.Add(x);
        }
        //double[] values=hist.Values;

        Console.WriteLine("Histogram");
        Console.WriteLine("{0,12} {1,12}", "Value", "Quantity");            
        for(int i=0; i<=10; i++)
        {
            double x=(i/10d);
            Console.WriteLine("{0,12} {1,12}", x, hist[x]);
        }
        Console.ReadLine();
    }

結果で

   Histogram
   Value     Quantity
       0           52
     0.1           97
     0.2          117
     0.3           98
     0.4           93
     0.5          110
     0.6           97
     0.7           94
     0.8           98
     0.9           93
       1           51

そしてコード:

public class Historgram<T> 
{
    Dictionary<T, int> bins;
    public Historgram()
    {
        this.bins=new Dictionary<T, int>();
    }

    public void Add(T value)
    {
        if(bins.ContainsKey(value))
        {
            bins[value]++;
        }
        else
        {
            bins.Add(value, 1);
        }
    }
    public void Remove(T value)
    {
        if(bins.ContainsKey(value))
        {
            bins[value]--;
            if(bins[value]==0)
            {
                bins.Remove(value);
            }
        }
    }
    public int this[T x]
    {
        get
        {
            if(bins.ContainsKey(x))
            {
                return bins[x];
            }
            else
            {
                return 0;
            }
        }
        set
        {
            if(bins.ContainsKey(x))
            {
                bins[x]=value;
            }
            else
            {
                bins.Add(x, value);
            }
        }
    }
    public bool ContainsValue(T value) { return bins.ContainsKey(value); }
    public int Count { get { return bins.Count; } }
    public T[] Values { get { return bins.Keys.ToArray(); } }
    public int[] Quantities { get { return bins.Values.ToArray(); } }
}
于 2013-02-05T21:01:44.837 に答える
2

そのような場合にジェネリックを使用する本当の理由はありません。ジェネリック引数はコンパイル時に不明であるため、コンパイラは、追加または削除しようとしているオブジェクトがそのリストに適しているかどうかを確認できません。

可能であれば、この状況を完全に回避することをお勧めします。おそらく、このコード自体がジェネリックになるようにすることです。

それが不可能な場合は、おそらく非ジェネリックArrayListまたは aList<object>を使用する方がよいでしょう。このコンテキストでジェネリック リストを使用すると、追加のヘルプなしで多くの余分な作業が追加されるためです。

于 2013-02-05T20:31:26.230 に答える
2

MakeGenricTypeが機能する可能性があります

Reflection を使用して List<CustomClass> 型のプロパティを設定する

    Type type = Program.CheckType(someInput);
    IList list = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
    object obj = Activator.CreateInstance(type);
    list.Add(obj);
于 2013-02-05T20:37:14.537 に答える
2
Type t = Program.CheckType(someInput);
var l = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(t)); 
于 2013-02-05T20:37:33.530 に答える