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 推迟处理,

以上是关于C#如何将类型Type作为泛型T的参数T传递的主要内容,如果未能解决你的问题,请参考以下文章

将具有类型参数的类作为Java中泛型方法的类型参数传递

C# 泛型:如果 T 是返回类型,它也可以是 void 吗?如何将这些接口组合在一起?

C#学习笔记---基础入门

C#中的泛型,使用变量的类型作为参数[重复]

C#泛型 类型约束

如何在 Java 中将类型作为方法参数传递