C#如何将类型Type作为泛型T的参数T传递

C#里,需要实现根据一个变量System.Typet,调用方法Method<T>(),但是此时不知道如何根据t来填写这个T,请大家指导。知道里有人写过,但是感觉不靠谱。... C#里,需要实现根据一个变量System.Type t,调用方法Method<T>(),但是此时不知道如何根据t来填写这个T,请大家指导。知道里有人写过,但是感觉不靠谱。 展开
 我来答
makosharp
2014-01-22 · TA获得超过676个赞
知道小有建树答主
回答量:188
采纳率:100%
帮助的人:270万
展开全部

简单的例子:

bool Method<T>(bool parameter) where T:class

{return parameter;}


这是一个完整的泛型方法,限制符T:class表示了泛型T的类型限制,请在MSDN查找“泛型类型约束”词条http://msdn.microsoft.com/zh-cn/library/bb384067.aspx


使用泛型方法一般用于涉及泛型(T)的方法:

  1. 泛型参数里有至少一个类型,如Method<T1,T2>() where...

  2. 返回值里涉及泛型,如 List<T> Method<T>() where...

  3. 方法内部需要以参数泛型类型为据做运算,如方法内容是 return T is IComparable;

  4. 参数中涉及不确定的类型,如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我。

百度网友c496c75
推荐于2016-01-22 · TA获得超过108个赞
知道小有建树答主
回答量:300
采纳率:100%
帮助的人:141万
展开全部
C# 的泛型都是以类或方法后加尖括号来传:fun<Type>()
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
zxyzcmpy
2014-01-21
知道答主
回答量:61
采纳率:0%
帮助的人:11.1万
展开全部
按你的字面的意思我可以理解为:
switch(Systen,Type)
case 1:
Method<1>();
breake;
default:
break;

这样能理解么?
追问
可以这么理解,但是这么写和if else没区别了,要把所有情况都考虑到。用泛型就是为了避免这种情况。
追答
他的 T 是个 object 类型,你用这个接口、方法的时候传一个类型过去,你传的什么他就是什么。
应该是Helper类里面封装的一个方法,很久以前见过。我们的类型都是自己控制的还真没怎么用到过泛型。只有申明集合的时候才用到。这种用的时候始终都要传类型过去的 多个类型的时候 就用 parameter或者直接封装到Sql里面给他执行了,再用一次泛型还没必要的地步。
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
谦图集Cr
2018-02-27 · TA获得超过323个赞
知道答主
回答量:450
采纳率:33%
帮助的人:89.4万
展开全部
推迟处理,
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式