看到他我一下子就悟了-- 泛型(1)

简介: 1.泛型概念:       本质上,术语”泛型”指的是”参数化类型(parameterized types)”.参数化类型非常重要,因为它们可以在创建类.结构.方法和委托的时候将要操作的数据类型作为参 数进行指定.使用参数化类型的类.结构.方法和委托都可以称为泛型,如”泛型类”或者”泛型方法”.        在具体声明一个变量或者实例化之前,类型参数T只是一个占位符。

1.泛型概念:


      本质上,术语”泛型”指的是”参数化类型(parameterized types).参数化类型非常重要,因为它们可以在创建类.结构.方法和委托的时候将要操作的数据类型作为参

数进行指定.使用参数化类型的类.结构.方法和委托都可以称为泛型,”泛型类”或者”泛型方法”.

       在具体声明一个变量或者实例化之前,类型参数T只是一个占位符。等到具体声明和实例化的时候,编译器要求代码指定类型参数。泛型类型声明了泛型数占位符类型,由泛型类型的用户填写这些占位符,并作为泛型的参数提供给泛型类型.

 

2.泛型约束:约束声明了泛型要求的类型参数的特征。

    为了声明一个约束,需要使用where关键字,后跟一对”参数:要求.其中,”参数”必须是泛型类型中定义的一个参数,”要求”用于限制类型从

中”派生”的类口,或者限制必须存在一个默认构造器,或者限制使用一个引用/值类型约束.

2.1基类约束(where T:base-class-name)

       有的时候,你可能需要限制类型从一个特定的类派生.这是用基类约束(base class constraint)做到的.使用基类约束,可以指定某个类型实参

必须继承的基类.基类约束有两个重要功能.

  首先,他允许在泛型类中使用由约束指定的基类所定义的成员.例如,可以调用基类的方法或者使用基类的属性.如果没有基类约束,编译器就无法知道某

个类型实参拥有哪些成员.通过提供基类约束,编译器将知道所有的类型实参都拥有由指定的基类所定义的成员.


  基类约束的第二个功能是,确保只适用支持指定基类的类型实参.这意味着对于任意给定的基类约束,类型实参要么是基类本身,要么是派生于该基

类.如果试图使用没有匹配或者继承指定的类型实参,就会导致编译错误 例:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//泛型:基类约束
//基类约束两个作用:1.基类约束允许泛型类访问基类的成员
// 2.确保只能使用满足该约束的类型参数,从而实现类型安全
namespace generic
{
/*案例描述:假设要创建一个管理电话号码列表的工具.另外,假定不同组的用户
使用的是不同的列表.例如,一个列表用于朋友,令外一个列表用于供应商等.
*/

/// <summary>
/// PhoneNumber基类,它用于存储姓名和姓名相对应的电话号码
/// </summary>
class PhoneNumber
{
public string Number { get; set; }
public string Name { get; set; }

public PhoneNumber(string n, string num)
{
this.Name = n;
this.Number = num;
}
}

/// <summary>
/// 朋友电话
/// </summary>
class Friend : PhoneNumber
{
/// <summary>
/// 电话号码是否为工作号码
/// </summary>
public bool IsWorkNumber { get; private set; }

public Friend(string n, string num, bool wk)
: base(n, num)
{
this.IsWorkNumber = wk;
}
}

/// <summary>
/// 供应商电话
/// </summary>
class Supplier : PhoneNumber
{
public Supplier(string n, string num)
: base(n, num)
{
}
}
/*为了管理电话列表,下面创建一个名为PhoneList的类.由于希望该类能够
* 管理任意类型的电话列表,因此将其实现为泛型.另外,由于列表管理的一部分内容是
* 根据姓名查询号码,或者根据号码查询姓名,因此要给它添加约束,从而
* 确保存储在列表中的对象的类型必须是PhoneNumber派生类的实例
*/

/// <summary>
/// 管理任意类型的电话列表
/// </summary>
/// <typeparam name="T"></typeparam>
class PhoneList<T> where T:PhoneNumber
{
T[] phList;

int end;

public PhoneList()
{
phList = new T[10];
end = 0;
}

public bool Add(T newEntry)
{
if (end == 10) return false;

phList[end] = newEntry;
end++;

return true;
}

public T FindByName(string name)
{
for (int i = 0; i < end; i++)
{
if (phList[i].Name == name)
return phList[i];
}

throw new NotFoundException();
}

public T FindByNumber(string number)
{
for (int i = 0; i < end; i++)
{
if (phList[i].Number == number)
return phList[i];
}

throw new NotFoundException();
}
}

/// <summary>
/// 此类没有继承PhoneNumber,因此不能用于创建PhoneList
/// </summary>
class EmailFriend
{
//.....
}
/*
* 这是一个定制异常,虽然该示例只使用默认构造函数,但是出于说明的
* 目的,NotFoundException实现了Exception定义的所有构造函数
* 注意:这些构造函数只调用了Exception定义的相等基类构造函数.
* NotFoundException没有向Exception添加任何内容,因此不需要
* 执行任何进一步的操作
*/
class NotFoundException : Exception
{
public NotFoundException():base(){}
public NotFoundException(string str):base( str){}
public NotFoundException(string str, Exception inner) :
base(str, inner) { }
protected NotFoundException(
System.Runtime.Serialization.SerializationInfo si,
System.Runtime.Serialization.StreamingContext se) :
base(si, se) { }
}
}

 

怎样调用:

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

namespace generic
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClassConstraint();
            Console.Read();
        }

        //基类约束
        public static void BaseClassConstraint()
        {
           //可以通过编译
            PhoneList<Friend> plist = new PhoneList<Friend>();
            //错误添加
            //plist.Add(new Friend() {Name="Tom",Number="555-1234",IsWorkNumber=true });
        //正确添加
            plist.Add(new Friend("Tom", "5555-333", true));
            plist.Add(new Friend("Gary", "5555-332", true));
            plist.Add(new Friend("WangC", "5555-331", false));


            try
            {
                Friend frnd = plist.FindByName("Gary");
                Console.WriteLine(frnd.Name+":"+frnd.Number);

                if(frnd.IsWorkNumber)
                    Console.WriteLine("(work)");
                else
                    Console.WriteLine();
            }
            catch (NotFoundException)
            {
                Console.WriteLine("Not Found");
            }

            //供应商
            PhoneList<Supplier> plist2 = new PhoneList<Supplier>();
            plist2.Add(new Supplier("Global Hardware", "400-123"));
            plist2.Add(new Supplier("Computer", "400-124"));
            plist2.Add(new Supplier("NetWorkCity", "400-125"));

            try
            {
                Supplier sp = plist2.FindByNumber("400-124");
                Console.WriteLine(sp.Name+":"+sp.Number);
            }
            catch (NotFoundException)
            {
                Console.WriteLine("Not Found");
            }

            //没有继承的
           // PhoneList<EmailFriend> plist3 = new PhoneList<EmailFriend>();
        }
    }
   
}

 未完待续……

目录
相关文章
|
缓存 运维 Java
nacos常见问题之点击下线提示报错如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
589 2
|
存储 机器学习/深度学习 PyTorch
深入理解GPU内存分配:机器学习工程师的实用指南与实验
给定一个模型架构、数据类型、输入形状和优化器,你能否计算出前向传播和反向传播所需的GPU内存量?
354 0
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用问题之全量和增量同步数据的一致性、不丢失和不重复读取可以通过什么方式保证
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
小程序 JavaScript Java
基于微信小程序的教育培训微信小程序的设计与实现(源码+lw+部署文档+讲解等)
基于微信小程序的教育培训微信小程序的设计与实现(源码+lw+部署文档+讲解等)
282 1
|
机器学习/深度学习 算法
m基于深度学习的64QAM调制解调系统相位检测和补偿算法matlab仿真
MATLAB 2022a仿真实现了基于深度学习的64QAM相位检测和补偿算法,有效应对通信中相位失真问题。通过DNN进行相位检测和补偿,降低解调错误。核心程序生成随机信号,模拟AWGN信道,比较了有无相位补偿的误码率,结果显示补偿能显著提升性能。
314 8
|
负载均衡 网络协议 安全
【计算机网络】虚拟路由冗余(VRRP)协议原理与配置
【计算机网络】虚拟路由冗余(VRRP)协议原理与配置
742 0
|
存储 分布式计算 数据挖掘
MaxCompute
MaxCompute是阿里云提供的一种大数据处理平台,它能够处理海量数据的存储和计算,提供PB级别的数据存储和处理能力。
1167 1
|
机器学习/深度学习 算法 数据挖掘
反向传播算法
反向传播算法
|
存储 数据挖掘 Windows
服务器数据恢复—异常断电导致raid信息丢失的数据恢复案例
由于机房多次断电导致一台服务器中raid阵列信息丢失。该阵列中存放的是文档,上层安装的是Windows server操作系统,没有配置ups。 因为服务器异常断电重启后,raid阵列可以正常使用,所以未引起管理员的注意。后续出现的多次异常断电导致raid报错,服务器无法找到存储设备,进入raid管理模块进行任何操作都会导致操作系统死机。管理员尝试多次重启服务器,故障依旧。