作者ccorn (玉米)
看板C_Sharp
标题[问题] 泛型使用时机/参数传入泛型或是interface
时间Thu Sep 6 17:28:15 2018
最近新学了泛型很开心,很多东西都可以拿来共用。
但是感觉自己有点走火入魔,用得太多,不知道参数到底要传入泛型还是介面。
写法一
public void DoSomething<T>(T obj)
where T: ISomething
写法二
public void DoSomething(ISomething obj)
之前常常写写法一,现在发现写法二也可以编译和正确执行
不知道写法一和写法二的差别是习惯问题还是根本用错泛型了...
希望有人可以替我解答,感谢!!
如果我真的用错泛型了,也想问一下泛型正确的使用时机是什麽?
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 59.120.231.91
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_Sharp/M.1536226098.A.8C9.html
1F:推 s4300026: 一样的方法定义用泛型,一样的方法宣告用介面09/06 19:09
2F:推 s4300026: (鱼,虫,人,菌),执行 “进食” 用介面。 (老师,09/06 19:22
3F:→ s4300026: 学生,家长,督察),执行 “用现金付帐” 用泛型。09/06 19:22
是说进食的实作根据物种差很多,用现金付帐的实作各种身份都一样吗?
那我有点不太懂为什麽用这两个状况判断泛型与否,是否跟楼下c大说的转型消耗有关?
感谢你的回应~
4F:推 CloudyWing: 以这范例来说,除非method里面可能会把介面转型成实际09/06 23:35
5F:→ CloudyWing: 型别,不然是2吧09/06 23:35
6F:推 CloudyWing: 以这情况,其实你呼叫起来几乎没差别,如果用介面就09/06 23:43
7F:→ CloudyWing: 不会有转型损耗的,其实用介面就可以了,有转型损耗的09/06 23:44
8F:→ CloudyWing: 就要考虑泛型或是泛型介面09/06 23:45
了解,那如果这样可以使用介面的状况写成泛型,会被当成dirty code或是不易读或是效
能差吗?
感谢你的回应~
※ 编辑: ccorn (116.241.1.187), 09/07/2018 00:27:16
※ 编辑: ccorn (116.241.1.187), 09/07/2018 00:56:04
9F:推 CloudyWing: 我个人觉得没太大差别,然後修正一下,说转型损耗不精09/07 01:32
10F:→ CloudyWing: 准,不用自行做型别检查或额外做转型09/07 01:34
11F:→ CloudyWing: DoSomething()里面如果只在意ISomething,例如只是呼09/07 02:02
12F:→ CloudyWing: 叫ISomething的某个方法,那就是介面就好 09/07 02:03
13F:→ CloudyWing: 但如果你在乎的是ISomething的延伸类别 09/07 02:04
14F:→ CloudyWing: 那你可能就必须在method去判断参数是ISomething的哪个 09/07 02:05
15F:→ CloudyWing: 延伸类别,或是利用泛型,让使用者可以延後到呼叫时决 09/07 02:09
16F:→ CloudyWing: 定,更简单来说是你是在定义method还是呼叫method决定09/07 02:10
17F:→ CloudyWing: 有效的型别来决定是interface还是泛型,感觉越讲越乱.09/07 02:11
18F:→ CloudyWing: 想到一个烂例子可以说明InterfaceA有定义methodA 09/07 02:39
19F:→ CloudyWing: ClassA实作MethodA;ClassB继承MethodA,new MethodA09/07 02:40
20F:→ CloudyWing: 上面打错,ClassB继承ClassA,又用new定义同名MethodA09/07 02:41
21F:→ CloudyWing: 如果你今天在意的是InterfaceA,不管传入参数型别是 09/07 02:43
22F:→ CloudyWing: 哪个,DoSomething()里呼叫都是实作介面的MethodA 09/07 02:44
23F:→ CloudyWing: 那就是作法二,如果你是要让呼叫DoSomething的人可以 09/07 02:46
24F:→ CloudyWing: 决定是要呼叫哪个Class的MethodA,那就是作法一 09/07 02:48
25F:→ CloudyWing: 当然正常不会用同名Method玩,而是搭配delegate使用 09/07 02:49
了解,那我还是乖乖改成介面好了><
其实我泛型用太多,同事有点看不懂
26F:推 s4300026: 不好意思,我把你的问题看成 "宣告方法" 时,要用介面 09/07 09:07
27F:→ s4300026: 还是泛型。09/07 09:07
28F:推 s4300026: 如果考虑传入值要用哪一种的话,能用介面,就用介面。09/07 09:17
29F:→ s4300026: 我会用泛型的情况,像是方法内会用到实作本体,像是new09/07 09:17
30F:→ s4300026: 之类的。09/07 09:17
了解,乖乖改成介面><
31F:→ testPtt: where T : new()09/07 09:59
我懂你 实体化时
32F:推 Litfal: 介面和委派可以给定in或out去指定输入或产出。你要从更高09/07 15:09
33F:→ Litfal: 的视野去理解这件事,这是SA的技能之一。09/07 15:10
我以为SA只是做文字的系统分析而已?!
34F:推 s4300026: 楼上的意思是,如果是介面,就可以只吞我定义的介面输入 09/07 18:43
35F:→ s4300026: ,但泛型的目标是我力求吞任何类型的输入 09/07 18:43
36F:→ s4300026: 是这样解释吗? 09/07 18:43
37F:推 CloudyWing: 32楼讲的是泛型介面才有,想知道可以查协变和逆变 09/08 10:35
之前看协变逆变看不太懂,这样一说就通了!这版强者真多><以後要多来发问了
※ 编辑: ccorn (116.241.1.187), 09/08/2018 23:00:01
38F:推 EnjoyLife000: 泛型是针对物件做处理 09/14 23:33
39F:→ EnjoyLife000: 介面是对物件做的规定 09/14 23:33
40F:→ EnjoyLife000: 经常两个会合在一起用,像是List<T>,里面有很多 09/14 23:34
41F:→ EnjoyLife000: ToXXX() 然後他会约束where T: 什麽介面或是Class 09/14 23:35
42F:→ EnjoyLife000: 但TOXXX都是针对T做操作。 如果今天你的Method里面 09/14 23:36
43F:→ EnjoyLife000: 针对T的类型都会呼叫同一个方法,这就要做介面 09/14 23:37
44F:→ EnjoyLife000: 推文好难回,到此为此.. 09/14 23:37