我们每个苹果都套个盒子,给每本书都套个盒子,但是苹果盒子和书盒子是不同的,

这样下去如果有更多的东西需要套盒子,1000种产品有1000种相应的盒子,造成类型极度膨胀非常难以维护。

    class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
AppleBox abox = new AppleBox() { Cargo = apple };
Console.WriteLine(abox.Cargo.Color); Book book = new Book() {Name = "New Book"};
BookBox bbox = new BookBox() { Cargo = book };
Console.WriteLine(bbox.Cargo.Name);
}
}
    class Apple
{
public string Color { get; set; }
}
class Book
{
public string Name { get; set; }
}
class AppleBox
{
public Apple Cargo { get; set; }
} class BookBox
{
public Book Cargo { get; set; }
}

我们只准备一种盒子,让这种盒子有不同属性可以装任何东西。

如果有1000种东西需要1000种盒子,在Box类种有1000个对应属性,每次只有1个有用,999个没有用。

另外如果又来了新的物品,则要修改Box类,增加新的属性。忘记增删属性会导致bug和代码不完善,这叫做成员膨胀。

    class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
Book book = new Book() { Name = "New Book" };
Box box1 = new Box() { Apple = apple };//用了Apple属性,没用Book属性
Box box2 = new Box() { Book = book };//反之
}
}
    class Apple
{
public string Color { get; set; }
}
class Book
{
public string Name { get; set; }
}
class Box
{
public Apple Apple { get; set; }
public Book Book { get; set; }
}

还有一种解决方案,那就是在声明Box的属性的时候 不要指明具体类型,用Object类型就可以了。

   class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
Book book = new Book() { Name = "New Book" };
Box box1 = new Box() { Cargo = apple };
Box box2 = new Box() { Cargo = book };
} }

Apple和Box类略

    class Box
{
public object Cargo { get; set; }
}

但是我们看不到Color属性了



如果想只当盒子里是Apple的时候才看到Color属性,那么就强制类型转换(略)或者使用as操作符

            Console.WriteLine((box1.Cargo as Apple)?.Color);

其中,box1里是苹果,box2里是书,这里(box1.Cargo as Apple)表示对象,“?”表示如果是Apple则.Color,否则不执行。

但是依然很麻烦呀。

因此我们引入泛型!

    class Box<类型参数>
{
public 类型参数 Cargo { get; set; }
}

所谓类型参数就是一个标识符,是一个泛化的类型

因此我们给类型参数起名TCargo,T表示泛型

因此修改Box类为:

    class Box<TCargo>
{
public TCargo Cargo { get; set; }
}

Program类变为

    class Program
{
static void Main(string[] args)
{
Apple apple = new Apple() { Color = "Red" };
Book book = new Book() { Name = "New Book" };
Box<Apple> box1 = new Box<Apple>() { Cargo = apple };
Box<Book> box2 = new Box<Book>() { Cargo = book };
Console.WriteLine(box1.Cargo.Color);
Console.WriteLine(box2.Cargo.Name);
}
}

我们发现这样是可以根据装不同东西的盒子,点出不同的属性的,完美解决了问题。

泛型(Generic)类的使用原因和使用方式的更多相关文章

  1. Java基础之Comparable接口, Collections类,Iterator接口,泛型(Generic)

    一.Comparable接口, Collections类 List的常用算法: sort(List); 排序,如果需要对自定义的类进行排序, 那就必须要让其实现Comparable接口, 实现比较两个 ...

  2. C#泛型(Generic)

    一.什么是泛型 泛型(Generic)是C#语言2.0.通用语言运行时(CLR)2.0..NET Framework2.0推出来的新特性. 泛型为.NET框架引入类型参数(Type Parameter ...

  3. Boost源码剖析之:泛型指针类any

    C++是强类型语言,所有强类型语言对型别的要求都是苛刻的,型别一有不合编译器就会抱怨说不能将某某型别转换为某某型别,当然如果在型别之间提供了转换操作符或是标准所允许的一定程度的隐式转换(如经过非exp ...

  4. Java - 泛型 ( Generic )

    Java - 泛型 ( Generic )     > 泛型的特点         > 解决元素存储的安全性问题         > 解决获取数据元素时,需要类型强转的问题     ...

  5. Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口

    Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...

  6. RestTemplate将响应数据转换为具有泛型的类对象

    前言: 重要,RestTemplate在SpringBoot项目里即便通过HttpMessageConverters添加了Fastjson且优先级比jackson要高也不会在RestTemplate里 ...

  7. JavaWeb_泛型(Generic)

    JDK5以前,对象保存到集合中就会失去其特性,取出时通常要程序员手工进行类型的强制转换,这样不可避免的就会引发程序的一些安全性问题.例如: ArrayList list = new ArrayList ...

  8. Dephi泛型generic的应用

    Dephi泛型generic的应用   泛型在C++, C#中已有广泛应用,Delphi自2009版本也引入泛型,典型的应用如TList,TDictionary.如果你熟悉C#,其用法十分类似. 比如 ...

  9. 泛型(Generic)

    当集合中存储的对象类型不同时,那么会导致程序在运行的时候的转型异常 import java.util.ArrayList; import java.util.Iterator; public clas ...

随机推荐

  1. testparm - 检查smb.conf配置文件的内部正确性

    总览 testparm [-s] [-h] [-L servername] [configfilename] [hostname hostIP] 描述 此程序是samba套件的一部分. testpar ...

  2. KiCAD绘制电源符号

    KiCAD绘制电源符号 KiCAD自带的电源符号有时候不符合我们的操作习惯,需要自己重新定义电源符号,这时候就需要新建(不能更改系统自带库的电源符号) 1.新建符号,参照下图行设置 2.放置引脚和图形 ...

  3. SpringCloud---分布式服务跟踪---Spring Cloud Sleuth

    1.概述 1.1 为什么要用到服务跟踪? 随着业务的发展,系统规模也会变得越来越大,各服务之间的调用关系也变得越来越错综复杂: 通常一个由客户端发起的请求   在后端系统中会经过多个不同的微服务调用  ...

  4. mongodb数据库管道操作

    1.$project(修改文档的结构,可以用来重命名.增加或删除文档中的字段) db.order.aggregate([ { $project:{ rade_no:1, all_price:1} } ...

  5. VMware Network Adapter VMnet1/8详解

    转自:https://www.cnblogs.com/systemnet123/articles/2640883.html VMWare提供了三种工作模式,它们是bridged(桥接模式).NAT(网 ...

  6. hdu2089数位DP

    旁听途说这个名字很久了,了解了一下. 改题目的意思是给你若干区间,让你找寻区间内不含62或4的数. 首先暴力必然T...那么实际上就是说,想办法做一种预处理,在每次输入的时候取值运算就可以了. 既然是 ...

  7. Machine Learning 之二,什么监督性学习,非监督性学习。

    1.什么是监督性学习?Supervised  Machine Learning. 在监督性学习,我们给定一个数据集以及我们已经知道正确输出的结果,然后找到一个输入和输出的关系. In Supervis ...

  8. 海外版本Google登录

    海外版本: 1.安裝谷歌安裝器:手机浏览器搜索“谷歌安装器”,安装酷安的好一些,地址: https://www.coolapk.com/apk/com.goplaycn.googleinstall 2 ...

  9. Dubbo入门到精通学习笔记(十五):Redis集群的安装(Redis3+CentOS)、Redis集群的高可用测试(含Jedis客户端的使用)、Redis集群的扩展测试

    文章目录 Redis集群的安装(Redis3+CentOS) 参考文档 Redis 集群介绍.特性.规范等(可看提供的参考文档+视频解说) Redis 集群的安装(Redis3.0.3 + CentO ...

  10. Leetcode刷题——007.整数反转

    上代码: #include <cmath> class Solution { public: int reverse(int x) { ; long long tx=llabs(x); ) ...