亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C#的泛型的類型參數可以有帶參數的構造函數的約束方式嗎?

2019-11-17 03:13:40
字體:
來源:轉載
供稿:網友

C#的泛型的類型參數可以有帶參數的構造函數的約束方式嗎?

Review后看到標題讓我十分羞愧自己語文功底太差,估計...請見諒......我還特地把這句寫回開頭了......

問題

前天遇到的一個問題,所以在MSDN發了個問,剛也豐富了下問題,關于泛型的。

最近用EF嘗試DDD常常有些奇怪的想法,比如“EF的Model First能否添加泛型支持”。這次是“泛型的類型能否有帶參數的約束方式”。

具體想法很簡單,在我使用泛型的時候,我發現我需要實例化一個類型參數:

1 class MyClass<T>2 {3     public MyClass1()4     {5         this.MyObject = new T();6     }7 8     T MyObject { get; set; }9 }

當然,上面會報錯。

錯誤內容是T沒有一個new約束(new constraint),查閱下MSDN,得到了泛型的類型參數的new約束的內容。

所以接下來正確的代碼就是:

 1 class MyClass<T> 2     where T : new() 3 { 4     public MyClass1() 5     { 6         this.MyObject = new T(); 7     } 8  9     T MyObject { get; set; }10 }

然后,后來我發現,我需要根據參數來創建新的對象,而且該方法在泛型的構造函數中實現最合適,所以我希望有這樣的代碼:

 1 class MyClass1<T> 2     where T : new(string) 3 { 4     public MyClass(string request) 5     { 6         this.MyObject = new T(request); 7     } 8  9     T MyObject { get; set; }10 }

可惜這下就錯大了,然后查閱泛型的約束方式列表,發現根本沒有帶參數的構造函數這種約束。

所以就發生了我上面在MSDN上問的那個問題,尋求一個“優雅的解決方案”。

一般解決方案就像問題中的回答那樣有兩種,也是我試過但是很不爽的兩種,我們依次看看。

補充:

  • 由James.Ying提醒,還有從構造函數傳入
  • 由@Choo提醒,用Activator.CreateInstance

工廠模式

首先是Factory Pattern,就是建一個工廠類,先看看代碼,這是其中一種寫法,請不要糾結在Factory Pattern上:

 1 class MyClass<T, TFactory> 2     where TFactory : IFactory<T>, new() 3 { 4     public MyClass(string request) 5     { 6         var factory = new TFactory(); 7  8         this.MyObject = factory.New(request); 9     }10 11     T MyObject { get; set; }12 }13 14 interface IFactory<T>15 {16     T New(string request);17 }

實現中你會發現,這樣需要為每個派生類或者實例類別創建并維護一個Factory類,那樣泛型本身就沒那么大意義了,本來就是為了減少類型重用邏輯而采用泛型的。

抽象基類的靜態抽象方法

如果不想維護多一個類,那么就在目標類本身下手,所以我們可以為目標類創建一個基類:

 1 class MyClass<T> 2     where T : TBase, new() 3 { 4     public MyClass(string request) 5     { 6         this.MyObject = T.New(request); 7     } 8  9     T MyObject { get; set; }10 }11 12 abstract class TBase13 {14     public abstract static TBase New(string request);15 }

為了防止誤人子弟,首先要說在前頭的是,這樣寫是會編譯錯誤的!

約束上是沒錯的,但是它報的錯誤是類似于“T是個類型參數,不能這么用!”('T' is a 'type parameter', which is not valid in the given context)。

從構造函數傳入

還有一種基礎的做法反而忘記了,由James.Ying提醒想起來,就是從泛型類的構造函數傳入。

class MyClass<T>    where T : TBase, new(){    public MyClass(T myObject)    {        this.MyObject = myObject;    }    T MyObject { get; set; }}

這種方式使得泛型類簡潔多了,把實例化的過程交給了調用者,有點依賴倒置了(其實凡是應該在泛型里實現的而交給了調用者或者繼承者都是這樣)。

優點是泛型簡單了,缺點就是你無法保證實例化使用的構造函數是T(string)。另外,它可能會降低代碼的重用性。假設實例化是有條件地,而且所有派生類的邏輯是統一的,那么還是在泛型基類中實現比較好。

簡單情況下這是對泛型來說最優雅的方式了。

Activator.CreateInstance

該方法可以在http://msdn.microsoft.com/en-us/library/system.activator.createinstance(v=vs.110).aspx見到,說明就比較明確了:

用最匹配的構造函數創建一個類型的實例(Creates an instance of the specified type using the constructor that best matches the specified parameters)。

寫法也很爽:

class MyClass<T>{    public MyClass(string request)    {        this.MyObject = (T)Activator.CreateInstance(typeof(T), request);    }    T MyObject { get; set; }}

這種方法做得到,也很簡短,也不用多做接口和基類。

缺點就是沒有約束,沒辦法保證T能有帶指定數量和類型參數的構造函數,或者是否有構造函數。

如果T不符合設計需求的話會報相應的異常。

原來泛型的類型參數是這么設計的

至此,便可以知道,C#的泛型里,類型參數是一種“非類”的存在,類型參數的約束(Constraints on Type Parameters)僅僅是用來描述具體的類在實例化或者繼承時所需要達到的條件。而在泛型內部,類型參數僅僅是一種“特別的存在”,它用來描述類,但卻無法用作類。

那么,類型參數可以有......參考本文題目......

首先,其實這個問題本身就是泛型的類型參數能否有帶參數的實例化方式,比如T myObject = new T("Hello World!“)。

然后,由于類型參數是用“約束”的方式來進行實例類的特點的描述的,所以,問題才變成了泛型的類型參數能否有帶參數的構造函數的約束方式,比如where T : new(string)。

要做假設的話,起始就是個證偽的問題,要證明它存在是否會造成什么原則問題。

首先能對比的就是泛型的類型參數已經有了不帶參數的構造函數的約束方式了,那么泛型的類型參數就算有帶了參數的構造函數的約束方式又如何?至少,泛型的類型參數已經有了不帶參數的構造函數的約束方式證明了泛型的類型參數有構造函數的約束方式并不會造成什么問題而且技術上是可以實現的。(......)

在我們實例化一個新對象的時候通常會用兩種初始化方式:

  • 利用構造函數傳參
  • 實例化后賦值

大部分情況下兩種方式產生的結果是差不多的,這種大部分情況是指一般所涉及到的屬性或參數都是公開的(public),本來就是開放讀寫的,所以內部寫和外部寫都差不多。

但遇到一些情況,比如一些業務約束,需要對參數進行處理或者利用參數進行操作,最終操作結果是私密的(PRivate),那么就會偏向于選用構造函數傳參?;蛘邥褂靡粋€特殊的方法,由該方法在類實例化之后再把需要的數據帶進來進行操作,這么做些許有失“一氣呵成”的爽快。

利用構造函數傳參并不是什么容易替代的方式,因為它在絕大部分屬于它的場景里都是最優的解決方案。有時候,初始化一個對象到使用,一氣呵成是最好的,因為這個事務本身就有很強的原子性。一個對象的兩種初始化方式造成了雙入口的麻煩,作為該類的使用者,有時候你會模糊,兩種方式所產生的結果你無法準確地把握;對于開發者,兩種實現方式供的出現在規范上也要求要么二選一,要么保證兩者一致。當類變得相對復雜的時候,事情就沒那么簡單了。

所以,我們確實會需要泛型的類型參數有帶了參數的構造函數的約束方式的一些場景。它雖然不是必要的,但是絕對是一種需要,就像get/set訪問器那樣。

補充地說,其實更大的命題是類型參數是否可以當作類使用

假設它可以由帶參數的構造函數約束了,那么可不可以直接如約束那樣當作類來使用呢?比如調用靜態方法?在泛型中創建繼承于該類型參數的類?

如此種種算來發現每一種都有可能是特例,而不是一個簡單的實現即可解決的。

比如調用靜態方法來說,T.Hello()所涉及的就是執行的時候T能明確是哪個類;而在泛型類中創建繼承于該類型參數的類就會變得復雜。

單單想想調用那個類的方法:MyClass<T>.MySubClass,這里的語法就有點“不一般”了,未必是一個“僅僅是泛型本身的問題”。

逼格高一點地說,越來越多的功能對C#或者任何一門語言來說是一條正確的道路嗎?

關于題目

如果你有不滿,可以提供合適的標題,禁止以任何方式攻擊作者!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
九色成人免费视频| 一区二区三区视频免费在线观看| 色悠悠久久久久| 欧美精品国产精品日韩精品| 在线观看日韩www视频免费| 久久久精品欧美| 波霸ol色综合久久| 国产亚洲精品久久久久久777| 国产亚洲欧洲高清一区| 98精品国产高清在线xxxx天堂| 日韩av在线免费播放| 亚洲午夜未删减在线观看| 欧美在线欧美在线| 亚洲伊人第一页| 国产成人aa精品一区在线播放| 亚洲欧洲在线播放| 中文字幕日韩精品在线| 狠狠躁夜夜躁久久躁别揉| 国产aaa精品| 久久成人一区二区| 中文欧美日本在线资源| 久久资源免费视频| 日韩专区在线播放| 久久久久久这里只有精品| 红桃av永久久久| 国产精品激情av在线播放| 欧美黑人巨大精品一区二区| 日本精品一区二区三区在线| 国产美女精品视频| 欧洲亚洲女同hd| 国产欧美一区二区三区视频| 欧美激情久久久| 日韩精品在线第一页| 日本成人免费在线| 欧美日韩一区二区在线| 国产免费亚洲高清| 国产精品久久99久久| 午夜精品久久久久久久男人的天堂| 亚洲肉体裸体xxxx137| 日本精品性网站在线观看| 亚洲欧美成人一区二区在线电影| 日韩在线视频免费观看高清中文| 国产色视频一区| 精品国产31久久久久久| 欧美精品videofree1080p| 国产欧美日韩91| …久久精品99久久香蕉国产| 91大神福利视频在线| 欧美精品第一页在线播放| 亚洲肉体裸体xxxx137| 久久五月天综合| 日韩小视频在线观看| 欧美成年人网站| 亚洲二区中文字幕| 久久精品国产久精国产一老狼| www亚洲欧美| 久久久av一区| 欧美午夜女人视频在线| 欧美性在线观看| 国产成人91久久精品| 国产欧美日韩丝袜精品一区| 欧美日韩美女在线| 国产福利成人在线| 久久精品国产成人| 亚洲天堂久久av| 欧美日韩一区二区免费在线观看| 91探花福利精品国产自产在线| 亚洲成av人片在线观看香蕉| 伊人男人综合视频网| 中文字幕亚洲情99在线| 91成人在线视频| 久久国产精品久久精品| 亚洲丝袜在线视频| 亚洲国产天堂久久综合网| 亚洲欧美999| 欧美性猛交视频| 日韩精品视频在线观看免费| 中文字幕在线成人| 在线看日韩欧美| 亚洲美女福利视频网站| 日韩一区视频在线| 亚洲精品一区二区在线| 国模精品一区二区三区色天香| 亚洲精品美女网站| www.日韩.com| 亚洲国产欧美久久| 午夜精品理论片| 中文在线不卡视频| 亚洲va欧美va国产综合久久| 亚洲福利视频网站| 中文字幕精品久久| 国产一区二区三区直播精品电影| 在线不卡国产精品| 国产精品色视频| 久久久久久久影院| 欧美一区二区三区免费视| 最新国产精品亚洲| 日韩在线观看网站| 欧亚精品中文字幕| 欧美性开放视频| 欧美性xxxx极品hd欧美风情| 欧美日韩加勒比精品一区| 97在线视频免费播放| 色哟哟亚洲精品一区二区| 91国产中文字幕| 国产午夜精品视频免费不卡69堂| 国产精品麻豆va在线播放| 国产精品久久久久福利| 欧美精品国产精品日韩精品| 欧美日韩另类字幕中文| 日韩中文字幕精品| 欧美老女人www| 色香阁99久久精品久久久| 欧美猛男性生活免费| 久久免费视频在线观看| 日韩av片电影专区| 日产精品99久久久久久| 国产在线观看一区二区三区| 亚洲国产中文字幕在线观看| 精品久久久久久久久久久久久| 国产精品96久久久久久又黄又硬| 国产精品久久久久久久久久久不卡| 欧美激情一级二级| 国内精品久久影院| 亚洲精品ady| 国产欧美日韩丝袜精品一区| 免费不卡欧美自拍视频| 亚洲精品资源美女情侣酒店| 插插插亚洲综合网| 国产精品视频午夜| 亚洲天堂av在线免费观看| 国产99久久精品一区二区| 国产精品久久久久久久久免费看| 国产日韩在线观看av| 欧美大肥婆大肥bbbbb| www.日韩系列| 欧美第一页在线| 欧美国产乱视频| 久久人人97超碰精品888| 亚洲男人天堂2023| 亚洲精品之草原avav久久| 日韩中文有码在线视频| 精品一区二区三区四区在线| 久久精品色欧美aⅴ一区二区| 亚洲成人免费在线视频| 欧美精品久久久久久久免费观看| 亚洲国产中文字幕在线观看| 亚洲精品中文字| 亚洲第一精品久久忘忧草社区| 久久天天躁夜夜躁狠狠躁2022| 欧美精品一二区| 亚洲新中文字幕| 国产日韩综合一区二区性色av| 日韩中文字幕在线视频播放| 日韩黄色av网站| 91精品国产91久久久久| 国产精品草莓在线免费观看| 亚洲天堂视频在线观看| 97精品国产91久久久久久| 中文字幕亚洲欧美日韩2019| 亚洲人成电影网站色…| 国产精品极品尤物在线观看| 欧美高清性猛交| 成人福利在线观看|