泛型約束:介面約束、new()構造函數約束、組合約束(即多種約束合併)

来源:https://www.cnblogs.com/stickcsharp/archive/2019/07/04/11131878.html
-Advertisement-
Play Games

泛型 介面約束: 普通 單例模式: 上面用到的是類中一個方法來獲取類的唯一實例對象 那完全也可以用屬性的訪問器來初始化一個類的對象啊,如下: 調用的話:var str = Singleton.Instance.Outresult("我是輸出內容...."); 綜上:兩種方式實現單例 泛型 new() ...


泛型 介面約束:

using System;

namespace ConsoleApp1
{

    /*
     * 
     * 介面約束:where T:interfaceName
     * T是類型形參的名稱,interfaceName是介面名稱,
     * 介面約束是  指定某個類型實參必須實現的介面。
     * 它的兩個主要的功能和基類約束一樣,允許開發人員在泛型類中使用介面中的成員;確保只能使用實現了特定介面的類型實參。
     *  也就是說,對任何給定的介面約束,類型實參必須是介面本身或者是實現了該介面的類。
     *  
     */



    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Compare<int>.CompareData(3, 12));//12
        }
    }

    /// <summary>
    /// 介面約束,T的類型用IComparable這個介面來約束
    /// 也就是說T的類型就是IComparable介面,用T可以調用它裡面的任何方法,只要你願意,這也就實現了介面約束的目的,即你要使用我這個介面,就必須按照我的規定來!
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Compare<T> where T : IComparable
    {
        // 定義一個方法,返回值類型為 T , 其兩個形參也是T類型的
        // 方法的功能:返回較大值
        public static T CompareData(T n1,T n2)
        {
            // 調用IComparable介面中方法CompareTo(),這個方法的返回值類型為int
            return n1.CompareTo(n2) > 0 ? n1 : n2;

            //先不考慮兩值相等的時候
        }
    }
}



普通 單例模式:

 

class Program
{
    static void Main(string[] args)
    {
        //使用單例:類名.靜態方法()  <----獲取到實例對象,然後再用對象調用它裡面的其他方法即可
        var str = Singleton.getInstance().Outresult("我是輸出內容....");
        Console.WriteLine(str);
    }
}


/// <summary>
/// 單例模式-----即一個函數只允許有一個實例對象!
/// </summary>
public class Singleton
{
    // 首先定義一個Singleton類型的對象(必須靜態的,不然調用它還要實例化,相悖了....),intance就是Singleton類的唯一實例對象
    public static Singleton instance;

    // 一個獲取實例對象的方法
    public static Singleton getInstance()
    {
        // 只有當Singleton類型的對象不存在時(即本類的實例對象),才去創建這樣一個對象!
        if (instance == null)
        {
            instance = new Singleton();
        }

        return instance;
    }

    // 本類中一個輸出方法(測試用的)
    public string Outresult(string str)
    {
        return str;
    }
}

上面用到的是類中一個方法來獲取類的唯一實例對象

那完全也可以用屬性的訪問器來初始化一個類的對象啊,如下:

public class Singleton
{
    public static Singleton instance;

    // 用屬性的get訪問器 生成單例的對象
    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }

    }
    //其他輸出方法......
}

調用的話:var str = Singleton.Instance.Outresult("我是輸出內容....");

綜上:兩種方式實現單例 

 

泛型 new()約束:父類是一個單例類

 

using System;

namespace ConsoleApp1
{

    /*
     * 
     * new()構造函數約束: where T: new()
     * 它允許開發人員實例化一個泛型類型的對象。
     * new()約束要求類型實參必須提供一個無參數的公有構造函數。
     * 使用new()約束時,可以通過調用該無參構造器來創建對象。
     * 
     * 註意:
     * 1. new()在與其他約束一起使用時,必須放在約束列表的末端
     * 2. 僅允許使用無參構造器構造一個對象,即使同時存在其他的構造器也是如此。即不允許給類型形參的構造器傳遞實參。
     * 3. 不可以同時使用new()約束和值類型約束。因為值類型都是隱式的提供一個無參公共構造器。就如同定義介面時指定訪問類型為public一樣,編譯器會報錯,因為介面一定是public的!!!
     *  
     */



    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Person.Instance.getPerson());

            Console.WriteLine(Student.Instance.getStudent());

            Console.WriteLine(Person.Instance.Outresult());

            Console.ReadKey();
        }
    }


    /// <summary>
    /// 單例模式-----即一個函數只允許有一個實例對象!
    /// </summary>
    public class Singleton<T> where T : new()
    {
        private static T instance;

        // 用屬性的get訪問器 生成單例的對象
        public static T Instance
        {
            get
            {
                if (instance == null)
                {
                    // 這裡創建的不再是一個Singleton對象,而是T對象
                    instance = new T();
                    // 這樣寫會報錯:變數類型 T 沒有new()約束,因此無法創建該類型的實例
                    //解決:類上面寫new()的約束......
                }
                return instance;
            }
        }

        // 本類中一個輸出方法(測試用的)
        public string Outresult()
        {
            return "this method in Singleton";
        }
    }


    /*
     * 對於繼承Singleton的類,必須要有一個無參構造器,因為他有new()約束!!! 
     * 
     */

    // Person類繼承Singleton類,就必須指定T的類型,這裡指定為Person....
    public class Person : Singleton<Person>
    {
        public string getPerson()
        {
            return "this method in Person class";
        }
    }

    public class Student : Singleton<Student>
    {
        public string getStudent()
        {
            return "this method in Student";
        }
    }
}

 

 

 

組合約束:

/*
*    五種約束:
* 
* where T:struct  值類型約束----類型參數必須為值類型
* 
* where T:class   引用類型約束:適用於類、介面、委托、數組等----類型參數必須為引用類型
* 
* where T:new()   new()約束-----類型參數必須有一個公有的無參構造器
* 
* where T:<base class name>   基類約束-----類型參數必須是指定的基類或是派生自指定的基類
* 
* where T:<interface>   介面約束-----類型參數必須是指定介面或實現指定的介面,可以指定多個介面約束,約束介面也可以是泛型的
* 
* 
* 組合約束:用的不多,基本都是別人封裝好的,我們拿來直接調用即可
* 同一個類型形參可以使用多個約束。逗號隔開
* 在約束列表中,第一個必須是引用類型約束或者值類型約束,或者是基類約束,然後才是介面約束,最後才是new()約束
* 指定引用類型約束或值類型約束的同時也指定基類約束是非法的
* 
* 例如:
* class Test<T> where T : Myclass, Interface, new(){......}
* 替換T的類型實參必須是繼承Myclass類,實現Interface介面,且擁有一個無參構造器
* 
* 在使用兩個或多個類型形參時,也可以使用多條where子句分別為它們指定約束
*  
*/

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在實際開發過程中,很多時候會拷貝一個現有的資料庫連接字元串,修改對應的資料庫名、用戶名、密碼等配置成新的資料庫連接字元串。但是有時候我們需要增加一些額外的配置,比如超時時間,最大連接池等,此時我們可以查找資料,其實可以使用Ado.Net 的SqlConnectionStringBuilder來構造數 ...
  • 跟同事合作前後端分離項目,自己對 WebApi 的很多知識不夠全,雖說不必要學全棧,可是也要瞭解基礎知識,才能合理設計介面、API,方便與前端交接。 晚上回到宿舍後,對 WebApi 的知識查漏補缺,主要補充了 WebAPi 的一些方法、特性等如何與前端契合,如何利用工具測試 API 、Axios ...
  • 在項目中總會用到son解析,比如RabbitMQ中使用json串解析,比如發過來的實體對象有50個欄位,而實際只需要用到裡面的幾個欄位,這時我們創建實體時,只需要創建需要的幾個欄位即可。 測試實例,首先定義實體 實體解析測試,可以創建解析實體,也可以不創建實體對象,直接使用匿名類解析 ...
  • 題目描述 輸入一個鏈表,按鏈表值從尾到頭的順序返回一個List。 解題思路 輸入一個鏈表,從尾到頭輸出,正常的遍歷都是從頭到尾輸出,而這裡需要從尾到頭輸出,那麼就是“先進後出”,也就是棧的功能。 代碼實現 棧的方式實現 遞歸的方式實現 想入非非:擴展思維,發揮想象 1.輸入一個鏈表,返回一個倒過來的 ...
  • 在談起java一家獨大的時候,dotnet人員總是一邊嘲笑大量濫竽充數的java從業者,一邊羡慕人家的生態。以前是只能羡慕,現在dotnet core開源了,我們都可以為dotnet core的開原生態貢獻自己的微薄之力。 WTM框架,一個基於 asp.net core 和 EF core的快速開發 ...
  • install-package PdfSharp -v 1.51.5185-beta ...
  • 在日常開發過程中,難免有這樣一種需求:就是你所建的每一個類文件或者介面文件都需要標註下作者姓名以及類的用途。如果我們每次創建文件的時候都需要寫一遍這些信息是很煩神的。還好Visual Studio給我們提供了模板註釋的功能來自動幫我們生成類似的註釋代碼。今天趁著中午休息的時間就讓我們一起來操作下吧。 ...
  • 題目描述 請實現一個函數,將一個字元串中的每個空格替換成“%20”。例如,當字元串為We Are Happy.則經過替換之後的字元串為We%20Are%20Happy。 解題思路 老實說,看到這個題目想到的就是字元串替換,但是面試題肯定不是這麼簡單的,那麼怎麼在原字元串上進行高效的替換呢?我們的字元 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...