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

作者: ccorn (玉米)   2018-09-06 17:28:15
最近新學了泛型很開心,很多東西都可以拿來共用。
但是感覺自己有點走火入魔,用得太多,不知道參數到底要傳入泛型還是介面。
寫法一
public void DoSomething<T>(T obj)
where T: ISomething
寫法二
public void DoSomething(ISomething obj)
之前常常寫寫法一,現在發現寫法二也可以編譯和正確執行
不知道寫法一和寫法二的差別是習慣問題還是根本用錯泛型了...
希望有人可以替我解答,感謝!!
如果我真的用錯泛型了,也想問一下泛型正確的使用時機是什麼?
作者: s4300026 (s4300026)   2018-09-06 19:09:00
一樣的方法定義用泛型,一樣的方法宣告用介面(魚,蟲,人,菌),執行 “進食” 用介面。 (老師,學生,家長,督察),執行 “用現金付帳” 用泛型。
作者: CloudyWing (孤單ㄉ翼)   2018-09-06 23:35:00
以這範例來說,除非method裡面可能會把介面轉型成實際型別,不然是2吧以這情況,其實你呼叫起來幾乎沒差別,如果用介面就不會有轉型損耗的,其實用介面就可以了,有轉型損耗的就要考慮泛型或是泛型介面我個人覺得沒太大差別,然後修正一下,說轉型損耗不精準,不用自行做型別檢查或額外做轉型DoSomething()裡面如果只在意ISomething,例如只是呼叫ISomething的某個方法,那就是介面就好但如果你在乎的是ISomething的延伸類別那你可能就必須在method去判斷參數是ISomething的哪個延伸類別,或是利用泛型,讓使用者可以延後到呼叫時決定,更簡單來說是你是在定義method還是呼叫method決定有效的型別來決定是interface還是泛型,感覺越講越亂.想到一個爛例子可以說明InterfaceA有定義methodAClassA實作MethodA;ClassB繼承MethodA,new MethodA上面打錯,ClassB繼承ClassA,又用new定義同名MethodA如果你今天在意的是InterfaceA,不管傳入參數型別是哪個,DoSomething()裡呼叫都是實作介面的MethodA那就是作法二,如果你是要讓呼叫DoSomething的人可以決定是要呼叫哪個Class的MethodA,那就是作法一當然正常不會用同名Method玩,而是搭配delegate使用
作者: s4300026 (s4300026)   2018-09-07 09:07:00
不好意思,我把你的問題看成 "宣告方法" 時,要用介面還是泛型。如果考慮傳入值要用哪一種的話,能用介面,就用介面。我會用泛型的情況,像是方法內會用到實作本體,像是new之類的。
作者: testPtt (測試)   2018-09-07 09:59:00
where T : new()
作者: Litfal (Litfal)   2018-09-07 15:09:00
介面和委派可以給定in或out去指定輸入或產出。你要從更高的視野去理解這件事,這是SA的技能之一。
作者: s4300026 (s4300026)   2018-09-07 18:43:00
樓上的意思是,如果是介面,就可以只吞我定義的介面輸入,但泛型的目標是我力求吞任何類型的輸入是這樣解釋嗎?
作者: CloudyWing (孤單ㄉ翼)   2018-09-08 10:35:00
32樓講的是泛型介面才有,想知道可以查協變和逆變
作者: EnjoyLife000 (Enjoy_Life)   2018-09-14 23:33:00
泛型是針對物件做處理介面是對物件做的規定經常兩個會合在一起用,像是List<T>,裡面有很多ToXXX() 然後他會約束where T: 什麼介面或是Class但TOXXX都是針對T做操作。 如果今天你的Method裡面針對T的類型都會呼叫同一個方法,這就要做介面推文好難回,到此為此..

Links booklink

Contact Us: admin [ a t ] ucptt.com