[英]How to generically instantiate a generic class in C#?
也許這很簡單,但是我沒有使用Type
,而是使用它。
假設我想根據某個函數的結果創建T
= Double
或T
= UInt32
的List<T>
,比如說public 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>();
我知道上面的代碼不會編譯,因為我讓l
具有兩種不同的含義(一個double列表和一個unsigned int列表)...因此它導致了我的問題 :
if
? 類似於以下內容:
Type t = Program.CheckType(someInput);
List<t> l = new List<t>(); // I know this won't compile either...
我的意思是,這通常會實例化一個通用列表...
先感謝您!
編輯:
這不是被標記問題 的重復 ,僅出於一個原因: Double
和UInt32
不是匿名類型! 這里的問題是如何確定某些輸入數據的類型 (例如,將是Type T
= typeof(Double)
或Type T
= typeof(UInt32)
,並因此基於 SampleClass<T>
創建通用的 SampleClass<T>
在該輸入數據類型上 , T
!
換句話說:確定一些Type T
在運行時,然后,實例化一個通用型與所確定的類型T
。 抱歉,如果我之前沒有明確說明...
PS:我使用List<T>
作為SampleClass<T>
的示例。
由於您不知道類型參數,因此無法以通用類型鍵入列表,但是可以在運行時創建List實例。
Type t = Program.CheckType(someInput);
Type listType = typeof(List<>).MakeGenericType(t);
IList list = (IList) Activator.CreateInstance(listType);
如果您嘗試添加錯誤類型的對象,則會得到異常,因此與使用ArrayList
或List<object>
類的集合相比,此方法具有優勢。
沒有真正的理由在這種情況下使用泛型。 由於在編譯時不知道泛型參數,因此編譯器無法驗證您要添加或刪除的對象是否適合該列表。
如果可能的話,最好完全避免這種情況,可能是通過使該代碼具有通用性的方法來避免。
如果不可能,最好使用非通用的ArrayList
或List<object>
,因為在這種情況下使用通用列表會增加很多額外的工作而沒有額外的幫助。
MakeGenricType可能有效
使用反射設置類型為List <CustomClass>的屬性
Type type = Program.CheckType(someInput);
IList list = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
object obj = Activator.CreateInstance(type);
list.Add(obj);
Type t = Program.CheckType(someInput);
var l = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(t));
我會選擇一個通用的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(); } }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.