>

自定义泛型那点事

- 编辑:www.bifa688.com -

自定义泛型那点事

 

 

泛型概述

泛型是程序设计语言的一种个性。允许技师在强类型程序设计语言中编辑代码时定义一些可变部分,这几个部分在使用前必须作出指明。各个程序设计语言和其编译器、运维碰到对泛型的支撑均分化等。将品种参数化以完成代码复用进步软件开荒工效的壹种数据类型。泛型类是援引类型,是堆对象,主即使引进了项目参数那些定义。

泛型定义

泛型的定义主要有以下三种:

一.在先后编码中某个暗含类型参数的花色,也等于说泛型的参数只好够代表类,不能够代表各自对象。(那是现行较分布的定义)

二.在程序编码中部分分包参数的类。其参数能够代表类或对象等等。(人们多数把那称之为模板)不论采纳哪个定义,泛型的参数在真的使用泛型时都必须作出指明。

一些强类型编制程序语言帮忙泛型,其主要目标是加强品类安全及缩小类转变的次数,但部分帮忙泛型的编制程序语言只可以落得部分目标。

 

正文

 倘使笔者想出口double ,int 和 dateTime类型的品类名字和他们的值。现在须求定义方法如下

using System;
using System.Data;

namespace testData
{
    class Program
    {
        static void Main(string[] args)
        {
            ShowInt(2);
            ShowDateTime(DateTime.Now);
            ShowDouble(2.52);
            Console.Read();
        }
        public static void ShowInt(int value)
        {
            Console.WriteLine($"typeName:{value.GetType().Name},Value:{value}");
        }
        public static void ShowDouble(double value)
        {
            Console.WriteLine($"typeName:{value.GetType().Name},Value:{value}");
        }
        public static void ShowDateTime(DateTime value)
        {
            Console.WriteLine($"typeName:{value.GetType().Name},Value:{value}");
        }
    }
}

那样写起来,好像比较艰巨,我们可不得以用一个主意来取代吗???

大家有的是初学者都接触过这四个泛型,

List<int> list = new List<int>();
Dictionary<int, string> dic = new Dictionary<int, string>();

首先个是列表,第二个大家称为字典,那么大家可不得以友善定义一个泛型方法呢????

泛型的语法结构及定义

泛型语法: 泛型类或方法的末尾 “<T>” T 是占位符,能够是任性字母,首要代表一个品种,假设是办法,参数就相应为占位符参数。 如 Show<T>(T t);方法,User<T> 类   。

泛型的特点:一.延缓注脚,2采取的时候在宣称

一.泛型方法的定义和动用

using System;
using System.Collections.Generic;
using System.Data;

namespace testData
{
    class Program
    {
        static void Main(string[] args)
        {
            Show<int>(1);
            Show<double>(1.904);
            Show<DateTime>(DateTime.Now);
            Show<string>("wbc");
            Console.Read();
        }
        public static void Show<T>(T t)
        {
            Console.WriteLine($"typeName:{t.GetType().Name},Value:{t}");
        }
    }
}

小编们会发觉,完全能够运营,一个办法就消除.那么大家可不得以简轻便单 <int> ,答案是必定的,当没有关联到装箱拆箱操作的时候,大家全然能够总结,如下

using System;
using System.Collections.Generic;
using System.Data;

namespace testData
{
    class Program
    {
        static void Main(string[] args)
        {
            Show(1);
            Show (1.904);
            Show(DateTime.Now);
            Show("wbc");
            User u = new User();
            Show(u);
            Console.Read();
        }
        public class User {

        }
        public static void Show<T>(T t)
        {
            Console.WriteLine($"typeName:{t.GetType().Name},Value:{t}");
        }
    }
}

 有人会说了,小编使用Object 作为参数,同样能够实现,为啥不接纳object呢,一切类型的父类是object ,应当能够的啊??,答案是料定的,也是足以的,知所以不应用,是因为使用object类型的时候,会发出装箱拆箱操作,这几个操作会损失精度。

 

2泛型类的概念和平运动用

泛型类的语法和泛型方法的语法很像,只是关键字是class ,如 Public Class MyGer<T>{

}

那么大家来看下泛型类的利用,看如下案列:

using System;
using System.Collections.Generic;
using System.Data;

namespace testData
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person()
            {
                Name="zhangsan",Age=28,Id=1,Id_No="110000198212193145",Address="beijiang",Sex="女"
            };
            MyGrenric<Person> gren = new MyGrenric<Person>();
            gren.Show(p);
            Console.Read();
        }


    }
    /// <summary>
    /// 人的父类
    /// </summary>
    public class BasePopleModel {

        public string  Name { get; set; }
        public int Age { get; set; }

        public string Address { get; set; }

        public string Id_No { get; set; }

        public string Sex { get; set; }
    }
    public class Pople {
        public string Name { get; set; }
        public int Age { get; set; }

        public string Address { get; set; }

        public string Id_No { get; set; }

        public string Sex { get; set; }
        public override string ToString()
        {
            string result = "{" $"name:{this.Name},age : {this.Age},sex : {this.Sex},no : {this.Id_No} " "}";
            return base.ToString();
        }
    }
    //人的信息
    public class Person : BasePopleModel {

        public int Id { get; set; }

        public override string ToString()
        {
            string result = "{ "  $"name : {base.Name},age : {base.Age},sex : {base.Sex},no : {base.Id_No} , id : {this.Id}" " }";
            return result;
        }
    }
    public class MyGrenric<T>
    {
        public void Show(T t) {
             Console.WriteLine(t);
        }
    }
}

 看了上面包车型大巴代码,我们得以看出,泛型类里面包车型大巴点子,能够是普通方法和泛型方法,当普通方法应用泛型的时候,我们得以简简单单泛型,上诉代码替换为:

 public void Show<T>(T t) {
             Console.WriteLine(t);
        }
是一样的结果。但是泛型类也有一个弊端,那就是失去了继承类的继承性质,如

BasePopleModel p = new Person()
{
Name="zhangsan",Age=28,Id=1,Id_No="110000198212193145",Address="beijiang",Sex="女"
};
MyGrenric<Person> gren = new MyGrenric<Person>();
gren.Show(p);

其暂时候,大家的代码就能报错。那什么在泛型中保留类的基础性,使用如下语法就能够达成:

必发88手机版 1必发88手机版 2

using System;
using System.Collections.Generic;
using System.Data;

namespace testData
{
    class Program
    {
        static void Main(string[] args)
        {
            BasePopleModel p = new Person()
            {
                Name="zhangsan",Age=28,Id=1,Id_No="110000198212193145",Address="beijiang",Sex="女"
            };
            MyGrenric<BasePopleModel> gren = new MyGrenric<BasePopleModel>();
            gren.Show(p);
            Console.Read();
        }


    }
    /// <summary>
    /// 人的父类
    /// </summary>
    public class BasePopleModel {

        public string  Name { get; set; }
        public int Age { get; set; }

        public string Address { get; set; }

        public string Id_No { get; set; }

        public string Sex { get; set; }
    }
    public class Pople {
        public string Name { get; set; }
        public int Age { get; set; }

        public string Address { get; set; }

        public string Id_No { get; set; }

        public string Sex { get; set; }
        public override string ToString()
        {
            string result = "{" $"name:{this.Name},age : {this.Age},sex : {this.Sex},no : {this.Id_No} " "}";
            return base.ToString();
        }
    }
    //人的信息
    public class Person : BasePopleModel {

        public int Id { get; set; }

        public override string ToString()
        {
            string result = "{ "  $"name : {base.Name},age : {base.Age},sex : {base.Sex},no : {base.Id_No} , id : {this.Id}" " }";
            return result;
        }
    }
    public class MyGrenric<T>
    {
        public void Show(T t) {
             Console.WriteLine(t);
        }


    }

    public interface Iccc<S> {

    }
}

View Code

当大家富有继续了BasePopleModel的子类,都得以利用这一个泛型类。

 

3泛型接口的定义和行使

咱俩来看下代码,定义一个泛型接口,和定义泛型类的语法结构是壹律的,他自家也负有接口的性状。代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp3
{
  public interface  IBaseImpl<T>
    {
         int State { get; set; }

        void Show(T t);
        void Search<S>(S s,T t);
    }
}

 

当大家普通类承继那几个泛型接口的时候,大家会发掘,承袭不了,生成编写翻译项目标时候,会提醒出错误音讯:如下图

必发88手机版 3

那大家来尝试,泛型类来承袭泛型接口,看好使不佳使,把大家地点成立的泛型类承继大家的接口(MyGrenric<T>:IBaseImpl<T>)如下:

 public class MyGrenric<T>:IBaseImpl<T>
    {
        public int State { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public void Search<S>(S s, T t)
        {
            throw new NotImplementedException();
        }

        public void Show(T t) {
             Console.WriteLine(t);
        }
    }

必发88手机版, 

大家开掘是能运营的.

于今主题素材来了,刚才我们的实例类承接泛型接口承袭不了,大家的实例类承继泛型类能承继吗??,有未有怎样措施,让我们的实例类承袭大家的泛型接口和泛型类呢?咱们先来探望,能还是无法实例类承接泛型类

必发88手机版 4

大家会意识照旧承袭不了:既然前边说了,T只是3个占位符,大家好还是倒霉来得的写出三个类呢??

必发88手机版 5

咱俩开采,那样是能够的,未有编写翻译错误,那么作者泛型类和泛型接口的占位符都以T,那么大家使用不相同的类可以吧??,答案是还是不是定的,相对不得以,贰个占位符只能表示三个体系,所以大家要运用差别的品种,就须求运用分裂的占位符,如:

必发88手机版 6

 

泛型约束

 前面学习了那样多自定义泛型的学问,我们着力就把全副泛型学习完了,大家事先一向都以说T,S,是泛型的四个占位符,能够是即兴等级次序,那大家能够限制那几个项目吗?答案是必然的,继续看图片

必发88手机版 7

经过上诉,大家能收看,大家限定了项目,只可以是Pople 类类型。限定语法,“唯有在泛型类和接口之后跟WHERE 泛型占位符 :类型”。

where T: 类型值 说明 限定规范
class 限定泛型只能是class 类型 可以有参数构造函数或无参数构造函数,不能和其他关键字一起使用
struct 限定泛型只能是struct类型 不可以和其他类型一起使用
new() 限定只能是类类型,切有无参数构造函数 必须有参数构造函数,不能和其他关键字一起使用
类类型 如果传入的是父类,则保留继承性质
值类型

那边就只是多演示上述内容,我们在此地只演示class ,代码如下

 

using System;
using System.Collections.Generic;
using System.Data;

namespace testData
{
    class Program
    {
        static void Main(string[] args)
        {
            BasePopleModel p = new Person()
            {
                Name="zhangsan",Age=28,Id=1,Id_No="110000198212193145",Address="beijiang",Sex="女"
            };
            MyGrenric<BasePopleModel> gren = new MyGrenric<BasePopleModel>();
            gren.Show(p);
            Console.Read();
        }
    }
    /// <summary>
    /// 人的父类
    /// </summary>
    public class BasePopleModel
    {

        public string  Name { get; set; }
        public int Age { get; set; }

        public string Address { get; set; }

        public string Id_No { get; set; }

        public string Sex { get; set; }
    }
    public class Pople {
        public string Name { get; set; }
        public int Age { get; set; }

        public string Address { get; set; }

        public string Id_No { get; set; }

        public string Sex { get; set; }
        public override string ToString()
        {
            string result = "{" $"name:{this.Name},age : {this.Age},sex : {this.Sex},no : {this.Id_No} " "}";
            return base.ToString();
        }
    }
    //人的信息
    public class Person: BasePopleModel   {

        public Person() {

        }
        public int Id { get; set; }


        public void Show(BasePopleModel s)
        {
            throw new NotImplementedException();
        }

        public override string ToString()
        {
            string result = "{ "  $"name : {base.Name},age : {base.Age},sex : {base.Sex},no : {base.Id_No} , id : {this.Id}" " }";
            return result;
        }
    }
    public class MyGrenric<T> where T :  class ,new()
    {

        public void Show(T t) {
             Console.WriteLine(t);
        }
    }

    //public interface IBaseImpl<S> where S : class
    //{
    //    int State { get; set; }

    //    void Show(S s);
    //}

}

 

计算:泛型类必须承继在泛型类上,假设作为普通类的父类,必须出示钦赐其连串,在封锁的时候,泛型类无法内定值类型的束缚。

泛型接口必须被泛型类和泛型接口承继,尽管被普通接口和普通类承袭,必须出示的内定项目,必须放在多少个持续文件的最终。在约束的时候,无法动用new()。

正文只是介绍常用的泛型使用方向,多数任何可行性未有详尽介绍,常用正是泛型类的施用,并不怎么涉及到泛型的承继,即使2个项目事关到泛型继承,注明那些种类也是快重构了。不过在支付进程中,泛型的束缚是时常采纳的。仅供参谋

另付二.0随后提供的常用泛型如下:

   2.0版的.NET框架类库提供了一个新的命名空间,System.Collections.Generic,个中带有了有个别一度足以利用的泛型容器类和连锁的接口。和早期版本的.NET框架提供的非泛型容器类比较,这个类和接口更敏捷且是类别安全的。在安排、落成自定义的容器类以前,请您思量是或不是选用或连续所列出类中的多少个。

 

    下边包车型地铁表格列出了新的泛型类和接口,旁边是相应的非泛型类和接口。在部分地点要尤其注意,如List<T>和Dictionary<T>,新泛型类的作为(behavior)与它们所替换的非泛型类有个别差异,也不完全同盟。更详细的内容,请参见System.Collections.Generic的文书档案

 

泛型类或接口

描述

对应的非泛型类型

Collection<T>

ICollection<T>

为泛型容器提供基类

CollectionBase

ICollection

Comparer<T>

IComparer<T>

IComparable<T>

比较两个相同泛型类型的对象是否相等、可排序。

Comparer

IComparer

IComparable

Dictionary<K, V>

IDictionary<K,V>

表示用键组织的键/值对集合。

Hashtable

IDictionary

Dictionary<K, V>.KeyCollection

表示Dictionary<K, V>中键的集合。

None.

Dictionary<K, V>.ValueCollection

表示Dictionary<K, V>中值的集合。

None.

IEnumerable<T>

IEnumerator<T>

表示可以使用foreach 迭代的集合。

IEnumerable

IEnumerator

KeyedCollection<T, U>

表示有键值的集合。

KeyedCollection

LinkedList<T>

表示双向链表。

None.

LinkedListNode<T>

表示LinkedList<T>中的节点。

None.

List<T>

IList<T>

使用大小可按需动态增加的数组实现 IList 接口

ArrayList

IList

Queue<T>

表示对象的先进先出集合。

Queue

ReadOnlyCollection<T>

为泛型只读容器提供基类。

ReadOnlyCollectionBase

SortedDictionary<K, V>

 表示键/值对的集合,这些键和值按键排序并可按照键访问,实现IComparer<T>接口。

SortedList

Stack<T>

表示对象的简单的后进先出集合。

Stack

本文由必发88手机版发布,转载请注明来源:自定义泛型那点事