泛型約束:介面約束、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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...