C#如何将类型Type作为泛型T的参数T传递
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#如何将类型Type作为泛型T的参数T传递相关的知识,希望对你有一定的参考价值。
C#里,需要实现根据一个变量System.Type t,调用方法Method<T>(),但是此时不知道如何根据t来填写这个T,请大家指导。知道里有人写过,但是感觉不靠谱。
简单的例子:
bool Method<T>(bool parameter) where T:class
return parameter;
这是一个完整的泛型方法,限制符T:class表示了泛型T的类型限制,请在MSDN查找“泛型类型约束”词条http://msdn.microsoft.com/zh-cn/library/bb384067.aspx
使用泛型方法一般用于涉及泛型(T)的方法:
泛型参数里有至少一个类型,如Method<T1,T2>() where...
返回值里涉及泛型,如 List<T> Method<T>() where...
方法内部需要以参数泛型类型为据做运算,如方法内容是 return T is IComparable;
参数中涉及不确定的类型,如Method<T>(List<T> param) where...
如果仅需要传入类型T而不需要返回涉及T的值,完全可以使用 Method(Type t)来替代。
应该注意的一点是,泛型方法存在的意义在于减少了非常多的冗余代码,它并不能消除或者自动处理如1楼中楼主所说的if/else逻辑(但是可以让你只写一次if/else而非几十上百次)。
我不太确定你到底想问什么,如果只是要单纯的用法,下面给你一个我现写的例子,该例子涉及上述4个使用场景。虽然看起来有点复杂,但是完全理解后熟练应用泛型方法不成问题。
我们的目标是:写一个方法,接收两个类型不定但继承自IEnumerable(可枚举接口)的参数,输出一个列表,其内是两个参数的每个元素比较大小后较大的元素的集合。例如,输入1,3,4,5和2,2,应该输出2,3,4,5。
现在我们分析一下,首先这个方法需要指出两个参数的类型,这里定为泛型类型T1和T2,这里的限定是IEnumerable,这样我们才可随意枚举这两个参数的元素。
由于要比较元素大小而元素的类型不确定,所以还需要一个泛型类型指定两个参数中元素的类型,这里用泛型类型TElement。因为需要比较大小,这里加上限定IComparable,以防调用者送进来根本不能进行Compare的元素类型。
加上我们期待的输出,方法的签名就是:
List<TElement> ElementsMax<TParam1, TParam2, TElement>(TParam1 p1, TParam2 p2)
where TParam1 : IEnumerable<TElement>
where TParam2 : IEnumerable<TElement>
where TElement : IComparable<TElement>
方法内容我这里直接写上了,不用细看,基本思路就是逐一取出两个参数序列的元素进行比较填入新序列。唯一需要注意的是两个参数序列的长度未必相等。
完整的方法,已测:
List<TElement> ElementsMax<TParam1, TParam2, TElement>(TParam1 p1, TParam2 p2)
where TParam1 : IEnumerable<TElement>
where TParam2 : IEnumerable<TElement>
where TElement : IComparable<TElement>
List<TElement> rtn = new List<TElement>();
int p1Length = p1.Count();
int p2Length=p2.Count();
for (int index = 0; index < Math.Max(p1.Count(), p2.Count()); index++)
//如果此p1和p2在index位置都有元素则比大小
//如果一方序列已空则判定未空的序列在index位置的元素为大
TElement compRslt = default(TElement);
if (index < p1Length && index < p2Length)
compRslt = p1.ElementAt(index).CompareTo(p2.ElementAt(index)) >= 0 ? p1.ElementAt(index) : p2.ElementAt(index);
else if (index < p1Length && index >= p2Length)
compRslt = p1.ElementAt(index);
else if (index >= p1Length && index < p2Length)
compRslt = p2.ElementAt(index);
//如果compRslt的值不是我们一开始构造的默认值,说明比较有结果,存储
if (compRslt.CompareTo(default(TElement))!=0)
rtn.Add(compRslt);
//btw,ICollection在Linq下有Zip方法可以条件式合并两个序列。
return rtn;
然后我们试试调用,可以直观的看到使用泛型方法的好处。
string outputStr;
//int测试
int[] array = new int[] 2, 1, 1, 6 ;
List<int> lst = new List<int> 3, 1, 5, 5, 9 ;
List<int> result= ElementsMax<int[], List<int>, int>(array, lst);
outputStr = "";
for (int index = 0; index < result.Count(); outputStr += result[index++].ToString() + ",") ;
MessageBox.Show(outputStr);
//char测试
string s1 = "Hello world";
Queue<char> s2 = new Queue<char>("Happy new year");
List<char> result2 = ElementsMax<string, Queue<char>,char>(s1, s2);
outputStr = "";
for (int index = 0; index < result2.Count(); outputStr += result2[index++].ToString()+",") ;
MessageBox.Show(outputStr);
//还可以迭代使用
int[] a1 = new int[] 1, 3, 5, 7, 9 ;
int[] a2 = new int[] 2, 4, 6, 8 ;
int[] a3=new int[]8,8,8,8,8;
List<int> result3 = ElementsMax<List<int>, int[], int>(ElementsMax<int[], int[], int>(a1, a2), a3);
outputStr = "";
for (int index = 0; index < result3.Count(); outputStr += result3[index++].ToString() + ",") ;
MessageBox.Show(outputStr);
实际的三组输出是:
3,1,5,6,9,
H,e,p,p,y, ,w,o,w,l,y,e,a,r,
8,8,8,8,9,
符合我们的预期。
就说到这里,有什么问题可以PM我。
参考技术A C# 的泛型都是以类或方法后加尖括号来传:fun<Type>() 参考技术B 按你的字面的意思我可以理解为:switch(Systen,Type)
case 1:
Method<1>();
breake;
default:
break;
这样能理解么?追问
可以这么理解,但是这么写和if else没区别了,要把所有情况都考虑到。用泛型就是为了避免这种情况。
追答他的 T 是个 object 类型,你用这个接口、方法的时候传一个类型过去,你传的什么他就是什么。
应该是Helper类里面封装的一个方法,很久以前见过。我们的类型都是自己控制的还真没怎么用到过泛型。只有申明集合的时候才用到。这种用的时候始终都要传类型过去的 多个类型的时候 就用 parameter或者直接封装到Sql里面给他执行了,再用一次泛型还没必要的地步。
以上是关于C#如何将类型Type作为泛型T的参数T传递的主要内容,如果未能解决你的问题,请参考以下文章