[問題] 泛型使用時機/參數傳入泛型或是interface

看板C_Sharp (C#)作者 (玉米)時間6年前 (2018/09/06 17:28), 6年前編輯推噓11(11033)
留言44則, 5人參與, 6年前最新討論串1/1
最近新學了泛型很開心,很多東西都可以拿來共用。 但是感覺自己有點走火入魔,用得太多,不知道參數到底要傳入泛型還是介面。 寫法一 public void DoSomething<T>(T obj) where T: ISomething 寫法二 public void DoSomething(ISomething obj) 之前常常寫寫法一,現在發現寫法二也可以編譯和正確執行 不知道寫法一和寫法二的差別是習慣問題還是根本用錯泛型了... 希望有人可以替我解答,感謝!! 如果我真的用錯泛型了,也想問一下泛型正確的使用時機是什麼? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.120.231.91 ※ 文章網址: https://www.ptt.cc/bbs/C_Sharp/M.1536226098.A.8C9.html

09/06 19:09, 6年前 , 1F
一樣的方法定義用泛型,一樣的方法宣告用介面
09/06 19:09, 1F

09/06 19:22, 6年前 , 2F
(魚,蟲,人,菌),執行 “進食” 用介面。 (老師,
09/06 19:22, 2F

09/06 19:22, 6年前 , 3F
學生,家長,督察),執行 “用現金付帳” 用泛型。
09/06 19:22, 3F
是說進食的實作根據物種差很多,用現金付帳的實作各種身份都一樣嗎? 那我有點不太懂為什麼用這兩個狀況判斷泛型與否,是否跟樓下c大說的轉型消耗有關? 感謝你的回應~

09/06 23:35, 6年前 , 4F
以這範例來說,除非method裡面可能會把介面轉型成實際
09/06 23:35, 4F

09/06 23:35, 6年前 , 5F
型別,不然是2吧
09/06 23:35, 5F

09/06 23:43, 6年前 , 6F
以這情況,其實你呼叫起來幾乎沒差別,如果用介面就
09/06 23:43, 6F

09/06 23:44, 6年前 , 7F
不會有轉型損耗的,其實用介面就可以了,有轉型損耗的
09/06 23:44, 7F

09/06 23:45, 6年前 , 8F
就要考慮泛型或是泛型介面
09/06 23:45, 8F
了解,那如果這樣可以使用介面的狀況寫成泛型,會被當成dirty code或是不易讀或是效 能差嗎? 感謝你的回應~ ※ 編輯: ccorn (116.241.1.187), 09/07/2018 00:27:16 ※ 編輯: ccorn (116.241.1.187), 09/07/2018 00:56:04

09/07 01:32, 6年前 , 9F
我個人覺得沒太大差別,然後修正一下,說轉型損耗不精
09/07 01:32, 9F

09/07 01:34, 6年前 , 10F
準,不用自行做型別檢查或額外做轉型
09/07 01:34, 10F

09/07 02:02, 6年前 , 11F
DoSomething()裡面如果只在意ISomething,例如只是呼
09/07 02:02, 11F

09/07 02:03, 6年前 , 12F
叫ISomething的某個方法,那就是介面就好
09/07 02:03, 12F

09/07 02:04, 6年前 , 13F
但如果你在乎的是ISomething的延伸類別
09/07 02:04, 13F

09/07 02:05, 6年前 , 14F
那你可能就必須在method去判斷參數是ISomething的哪個
09/07 02:05, 14F

09/07 02:09, 6年前 , 15F
延伸類別,或是利用泛型,讓使用者可以延後到呼叫時決
09/07 02:09, 15F

09/07 02:10, 6年前 , 16F
定,更簡單來說是你是在定義method還是呼叫method決定
09/07 02:10, 16F

09/07 02:11, 6年前 , 17F
有效的型別來決定是interface還是泛型,感覺越講越亂.
09/07 02:11, 17F

09/07 02:39, 6年前 , 18F
想到一個爛例子可以說明InterfaceA有定義methodA
09/07 02:39, 18F

09/07 02:40, 6年前 , 19F
ClassA實作MethodA;ClassB繼承MethodA,new MethodA
09/07 02:40, 19F

09/07 02:41, 6年前 , 20F
上面打錯,ClassB繼承ClassA,又用new定義同名MethodA
09/07 02:41, 20F

09/07 02:43, 6年前 , 21F
如果你今天在意的是InterfaceA,不管傳入參數型別是
09/07 02:43, 21F

09/07 02:44, 6年前 , 22F
哪個,DoSomething()裡呼叫都是實作介面的MethodA
09/07 02:44, 22F

09/07 02:46, 6年前 , 23F
那就是作法二,如果你是要讓呼叫DoSomething的人可以
09/07 02:46, 23F

09/07 02:48, 6年前 , 24F
決定是要呼叫哪個Class的MethodA,那就是作法一
09/07 02:48, 24F

09/07 02:49, 6年前 , 25F
當然正常不會用同名Method玩,而是搭配delegate使用
09/07 02:49, 25F
了解,那我還是乖乖改成介面好了>< 其實我泛型用太多,同事有點看不懂

09/07 09:07, 6年前 , 26F
不好意思,我把你的問題看成 "宣告方法" 時,要用介面
09/07 09:07, 26F

09/07 09:07, 6年前 , 27F
還是泛型。
09/07 09:07, 27F

09/07 09:17, 6年前 , 28F
如果考慮傳入值要用哪一種的話,能用介面,就用介面。
09/07 09:17, 28F

09/07 09:17, 6年前 , 29F
我會用泛型的情況,像是方法內會用到實作本體,像是new
09/07 09:17, 29F

09/07 09:17, 6年前 , 30F
之類的。
09/07 09:17, 30F
了解,乖乖改成介面><

09/07 09:59, 6年前 , 31F
where T : new()
09/07 09:59, 31F
我懂你 實體化時

09/07 15:09, 6年前 , 32F
介面和委派可以給定in或out去指定輸入或產出。你要從更高
09/07 15:09, 32F

09/07 15:10, 6年前 , 33F
的視野去理解這件事,這是SA的技能之一。
09/07 15:10, 33F
我以為SA只是做文字的系統分析而已?!

09/07 18:43, 6年前 , 34F
樓上的意思是,如果是介面,就可以只吞我定義的介面輸入
09/07 18:43, 34F

09/07 18:43, 6年前 , 35F
,但泛型的目標是我力求吞任何類型的輸入
09/07 18:43, 35F

09/07 18:43, 6年前 , 36F
是這樣解釋嗎?
09/07 18:43, 36F

09/08 10:35, 6年前 , 37F
32樓講的是泛型介面才有,想知道可以查協變和逆變
09/08 10:35, 37F
之前看協變逆變看不太懂,這樣一說就通了!這版強者真多><以後要多來發問了 ※ 編輯: ccorn (116.241.1.187), 09/08/2018 23:00:01

09/14 23:33, 6年前 , 38F
泛型是針對物件做處理
09/14 23:33, 38F

09/14 23:33, 6年前 , 39F
介面是對物件做的規定
09/14 23:33, 39F

09/14 23:34, 6年前 , 40F
經常兩個會合在一起用,像是List<T>,裡面有很多
09/14 23:34, 40F

09/14 23:35, 6年前 , 41F
ToXXX() 然後他會約束where T: 什麼介面或是Class
09/14 23:35, 41F

09/14 23:36, 6年前 , 42F
但TOXXX都是針對T做操作。 如果今天你的Method裡面
09/14 23:36, 42F

09/14 23:37, 6年前 , 43F
針對T的類型都會呼叫同一個方法,這就要做介面
09/14 23:37, 43F

09/14 23:37, 6年前 , 44F
推文好難回,到此為此..
09/14 23:37, 44F
文章代碼(AID): #1RaFCoZ9 (C_Sharp)
文章代碼(AID): #1RaFCoZ9 (C_Sharp)