我感觉这一条目应该算是对Item2的补充,还是在“约束”的条件下,如何使得程序得到最优化的结果,颇有“带着脚铐跳芭蕾”的意味。Item2中的条目可以看做是在有约束的情况下,对泛型类外部的影响;本条目可以看做是对泛型内部的影响。

通常情况下,.NET框架,或者我们自身针对不同项目制定的框架,都会包含一系列的接口或者基类,接口或者基类之间,会有继承的关系,形成一个系统的骨架,在此基础上根据具体的业务,对框架进行填充,使得最终的系统才会有血有肉。

在设计泛型类时,如果指定的“约束”是很宽泛的“约束”,即从类型层次结构上来看,“约束”指定的类型包含了子类型。那么可以在编写泛型方法时,对泛型参数的类型进行判断,如果该参数的类型属于某一种特定的类型(这里的特定类型一定会是泛型类型的子类型),那么就可以调用特定类型的方法,从而可以充分利用子类型的特点。

我们还是使用《More Effective C#》中提供的示例进行说明吧,来看下面的代码。

代码

1 public sealed class ReserseEnumerable<T> : IEnumerable<T>
2 {
3 private class ReserseEnumerator : IEnumerator<T>
4 {
5 int currentIndex;
6 IList<T> collection;
7 public ReserseEnumerator(IList<T> srcCollection)
8 {
9 collection = srcCollection;
10 currentIndex = collection.Count;
11 }
12
13 #region IEnumerator<T> Members
14
15 public T Current
16 {
17 get { return collection[currentIndex]; }
18 }
19
20 #endregion
21
22 #region IDisposable Members
23
24 public void Dispose()
25 {
26
27 }
28
29 #endregion
30
31 #region IEnumerator Members
32
33 object IEnumerator.Current
34 {
35 get { return this.Current; }
36 }
37
38 public bool MoveNext()
39 {
40 return --currentIndex >= 0;
41 }
42
43 public void Reset()
44 {
45 currentIndex = collection.Count;
46 }
47
48 #endregion
49 }
50
51 IEnumerable<T> sourceSequence;
52 public IList<T> originalSequence;
53
54 public ReserseEnumerable(IEnumerable<T> sequence)
55 {
56 sourceSequence = sequence;
57 }
58 #region IEnumerable<T> Members
59
60 public IEnumerator<T> GetEnumerator()
61 {
62 if (originalSequence == null)
63 {
64 originalSequence = new List<T>();
65 foreach (T item in sourceSequence)
66 {
67 originalSequence.Add(item);
68 }
69 }
70 return new ReserseEnumerator(originalSequence);
71 }
72
73 #endregion
74
75 #region IEnumerable Members
76
77 IEnumerator System.Collections.IEnumerable.GetEnumerator()
78 {
79 return this.GetEnumerator();
80 }
81
82 #endregion
83 }

上述代码实现了一个对列表进行反转的功能,它指定的“约束”是比较宽泛的,在代码中,并没有对泛型参数的类型再做进一步的判断和处理。

这里有必要说明一点,上面的代码是没有错误的,对于使用者来说,它从最大程度上开放了“约束”。但是在内部实现方面,我们还可以做以下优化,来看一下IReserseEnumerable<T>的构造函数,我们可以对其进行以下改动。

代码

1 public ReverseEnumerable(IEnumerable<T> sequence)
2 {
3 sourceSequence = sequence;
4 // If sequence doesn't implement IList<T>,
5 // originalSequence is null, so this works
6 // fine.
7 originalSequence = sequence as IList<T>;
8 }
9
10 public ReverseEnumerable(IList<T> sequence)
11 {
12 sourceSequence = sequence;
13 originalSequence = sequence;
14 }

对于GetEnumerator<T>方法来说,我们可以对其进行以下改动。

代码

1 public IEnumerator<T> GetEnumerator()
2 {
3 // Create a copy of the original sequence,
4 // so it can be reversed.
5 if (originalSequence == null)
6 {
7 if (sourceSequence is ICollection<T>)
8 {
9 ICollection<T> source = sourceSequence
10 as ICollection<T>;
11 originalSequence = new List<T>(source.Count);
12 }
13 else
14 originalSequence = new List<T>();
15 foreach (T item in sourceSequence)
16 originalSequence.Add(item);
17 }
18 return new ReverseEnumerator(originalSequence);
19 }

总结:我们可以在泛型约束的范围内,通过对泛型参数的类型进行判断和处理,这样在照顾到重用性的同时,也可以尽可能的提高程序的性能。

转载于:https://www.cnblogs.com/wing011203/archive/2010/03/22/1691944.html

More Effective C# Item3 : 运行时检查泛型参数的类型并提供特定的算法相关推荐

  1. java 运行时获取泛型真实类型

    前情提要 本文章用于运行时获取泛型的具体类型,有一些情况下可以获取到真实类型,有一些情况下获取不到的情况. Class 类的两个方法 /*** Returns the {@code Class} re ...

  2. Kotlin 知识梳理(13) 运行时的泛型

    一.本文概要 本文是对<<Kotlin in Action>>的学习笔记,如果需要运行相应的代码可以访问在线环境 try.kotlinlang.org,这部分的思维导图为: 二 ...

  3. C# 调用Dll中非托管C++代码时,函数参数的类型对照

    在上一篇blog(工具(Tray Friend):将任何程序,最小化到系统托盘 )中. 使用C#调用了很多非托管的C++代码. 现在就把"C# 调用Dll中非托管C++代码时,函数参数的类型 ...

  4. java 泛型参数具体类型获取、泛型返回具体类型获取

    自从java支持泛型后,现在,spring生态中的框架及目前的应用都使用了泛型.有的框架如mybatis和spring都需要反射获取类型,以使得序列化和反序列化得以实现,但有时候我们根据项目的需要获取 ...

  5. java 泛型参数的类型_Java获得泛型参数类型

    在Android开发中,使用Gson将json字符串转换为Java对象尤为常见.在这个转换过程中,通常会结合泛型参数.接口或者抽象类来封装处理. T t = new Gson().fromJson(r ...

  6. java 运行时路径_如何在运行时检查当前Java类路径(重复)

    下面的代码实现了Java 9 +(JigSAW)中的模块路径扫描.它查找调用堆栈上的所有类,然后对每个类引用调用 classRef.getModule().getLayer().getConfigur ...

  7. Linux笔记-查询进程,获取其运行时输入的参数

    背景 目前做了个进程管理软件,纯Qt做的,此软件包含3个进程,1个监控进程,1个保护进程,1个控制进程. 监控进程负责 需要管理的进程 的启停,并且与控制进程形成双进程守护. 监控进程打开了某TCP端 ...

  8. 使python脚本在运行时可以附带参数的方法

    sys模块获取单纯的参数 python demo.py a b c $ cat demo.py #-*- coding: UTF-8 -*- import os import sysdef demo( ...

  9. winform运行时如何接受参数?(示例)

    关键是在Main函数中处理,示例如下 using System; using System.Collections.Generic; using System.Windows.Forms; names ...

最新文章

  1. [CoolStuff]有趣的Zumobi
  2. Redis设置外网可访问
  3. DL之FAN:FAN人脸对齐网络(Face Alignment depth Network)的论文简介、案例应用之详细攻略
  4. javascript一个重要知识点:事件。
  5. 文件操作-小文件复制
  6. 现代软件工程系列 学生和老师都不容易
  7. 排序系列02--选择排序
  8. html记事本制作静态网页,记事本编辑html静态网页设计(3页)-原创力文档
  9. 3DMine V202006体验版本下载
  10. 【PyTorch】深度学习实战之PyTorch实现线性回归
  11. 学号在java是什么意思_在JAVA程序中增加姓名学号
  12. 思科交换机工作模式及基本命令
  13. 某Java大佬在地表最强Java企业(阿里)面试总结
  14. Java环境配置 win10教程
  15. JDO与Hibernate之比较(转载)
  16. Excel隔行插入空白行
  17. 给邮箱和手机号码打码
  18. 手机怎么申请邮箱?手机邮箱下载
  19. 如何应对 DDoS 勒索攻击?
  20. python多边形的绘制教程_绘制最新:python绘制封闭多边形教程_爱安网 LoveAn.com

热门文章

  1. 大家所推崇的Redis分布式锁真的就万无一失吗?
  2. MySQL 优化原理(三)
  3. 【Python】青少年蓝桥杯_每日一题_3.05_排列组合
  4. Java 面向抽象编程和面向接口编程
  5. Hibernate出现org.hibernate.MappingException: Unknown entity: com.gxuwz.hiberbate.entity.User的解决办法
  6. php图书信息浏览器,使PHP即时输出结果到浏览器
  7. 美国一大型数据中心将24h由光伏+储能供电
  8. 给数据中心来个例行“体检”——动力系统
  9. UPS不间断电源常见故障及如何排除故障
  10. 使鼠标保持按住状态_MouseInc 鼠标手势工具