如何在C#中一般实例化generics类?
也许这很简单,但我没有使用类型Type
和它的用途。
假设我想用T
= Double
或T
= UInt32
创建List
,具体取决于某些函数的结果,比如public static Type CheckType(String input);
在代码中:
Type t = Program.CheckType(someInput); // it returns typeof(Double) or typeof(UInt32) if (t == typeof(Double)) List l = new List(); else List l = new List();
我知道上面的代码不会编译,因为我让l
有两个不同的含义(一个double列表和一个unsigned int列表)……所以它引出了我的问题 :
- 有没有办法在上面的代码中避免使用
if
?
与此类似的东西:
Type t = Program.CheckType(someInput); List l = new List(); // I know this won't compile either...
我的意思是,这通常会实例化一个通用List …
先感谢您!
编辑:
这不是 标记问题 的重复 ,只有一个原因: Double
和UInt32
不是匿名类型! 这里的问题是如何确定某些输入数据的类型 (例如, Type T
= typeof(Double)
或Type T
= typeof(UInt32)
),因此, 创建一个基于 SampleClass
的通用 在那个输入数据类型上 , T
!
换句话说:在运行时确定一些Type T
,然后使用确定的类型T
实例化generics类型。 对不起,如果我之前没有说清楚……
PS:我使用List
作为SampleClass
的示例。
您不能将列表键入为通用列表,因为您不知道类型参数,但可以在运行时创建List实例。
Type t = Program.CheckType(someInput); Type listType = typeof(List<>).MakeGenericType(t); IList list = (IList) Activator.CreateInstance(listType);
如果您尝试添加不正确类型的对象,您将获得exception,因此这种方法优于使用ArrayList
或List
类的集合。
在这种情况下,没有真正的理由使用generics。 由于通用参数在编译时是未知的,因此编译器无法validation您尝试添加或删除的对象是否适合该列表。
如果可能的话,最好完全避免这种情况,可能是通过制作这个代码本身就是通用的方法。
如果那是不可能的,那么最好只使用非genericsArrayList
或List
,因为在此上下文中使用generics列表将添加许多额外的工作,无需额外帮助。
MakeGenricType可能有效
使用Reflection设置类型为List
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
但不要尝试将两种类型保存在同一个变量中,除非你想要一个IDictionary
变量。
以下是使用double
类型的直方图的示例:
class Program { static Random rnd=new Random(); static void Main(string[] args) { Historgram hist=new Historgram (); 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 { Dictionary bins; public Historgram() { this.bins=new Dictionary(); } 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(); } } }