12.Generics
benifit:


1.make developers extremely productive is code reuse, which is the ability to derive a class that inherits all of the capabilities of a base class.
The derived class can simply override virtual methods or add some new methods to customize the behavior of the base class to meet the developer’s needs.
2.is another mechanism offered by the common language runtime (CLR) and programming languages that provides one more form of code reuse: algorithm reuse.
such as sorting, searching, swapping, comparing, or converting
Most algorithms are encapsulated in a type, and the CLR allows the creation of generic reference types as well as generic value types.but it does not allow the creation of generic enumerated types.
3.Source code protection
The developer using a generic algorithm doesn’t need to have access to the algorithm’s source code.
With C++ templates, however, the algorithm’s source code must be available to the developer who is using the algorithm.
4.Type safety
When a generic algorithm is used with a specific type, the compiler and the CLR understand this and ensure that only objects compatible with the specified data type are used with the algorithm.
Attempting to use an object of an incompatible type will result in either a compiler error or a run-time exception being thrown.
In the example, attempting to pass a String object to the Add method results in the compiler issuing an error.
5.Cleaner code
Because the compiler enforces type safety, fewer casts are required in your source code, meaning that your code is easier to write and maintain.
In the last line of SomeMethod, a developer doesn’t need to use a (DateTime) cast to put the result of the indexer (querying element at index 0) into the dt variable.
6.Better performance
Before generics, the way to define a generalized algorithm was to define all of its members to work with the Object data type. If you wanted to use the algorithm with value type instances, the CLR had to box the value type instance prior to calling the members of the algorithm. boxing causes memory allocations on the managed heap, which causes more frequent garbage collections, which, in turn, hurt an application’s performance.
Because a generic algorithm can now be created to work with a specific value type, the instances of the value
type can be passed by value, and the CLR no longer has to do any boxing.
In addition, because casts are not necessary (see the previous bullet), the CLR doesn’t have to check the type safety of the attempted cast, and this results in faster code too.



using the generic List algorithm with the Int32 type is much faster than using the non-generic ArrayList algorithm with Int32.because using a value type (Int32) with ArrayList causes a lot of boxing operations to occur
using reference types is not as momentous.the times and number of garbage collections are about the same. So it doesn’t appear that the generic List algorithm is of any benefit here.
However, keep in mind that when using a generic algorithm, you also get cleaner code and compile-time type safety
So although the performance improvement is not huge, the other benefits you get when using a generic algorithm are usually an improvement.
其他知识:
1.Microsoft’s design guidelines state that generic parameter variables should either be called T or at least start with an uppercase T (as in TKey and TValue).
The uppercase T stands for type, just as an uppercase I stands for interface (as in IComparable).
2.the CLR generates native code for each method the first time the method is called for a particular data type. This will increase an application’s working set size, which will hurt performance
1.Generics in the Framework Class Library
1.the most obvious use.the FCL defines several generic collection classes available for your use(System.Collections.Generic namespace,System.Collections.ObjectModel namespace,System.Collections.Concurrentnamespace)
2.Microsoft recommends that programmers use the generic collection classes and now discourages use of the non-generic collection classes
(1)get the type safety, cleaner code, and better performance
(2)have a better object model.For example, fewer methods are virtual, resulting in better performance,and new members have been added to the generic collections to provide new functionality.
3.The collection classes implement many interfaces, and the objects that you place into the collections can implement interfaces that the collection classes use for operations such as sorting and searching.
The FCL ships with many generic interface definitions so that the benefits of generics can be realized when working with interfaces as well.
The commonly used interfaces are contained in the System.Collections.Generic namespace.
4.The new generic interfaces are not a replacement for the old non-generic interfaces;
in many scenarios,you will have to use both.The reason is backward compatibility.
For example, if the List<T> class implemented only the IList<T> interface, no code could consider a List<DateTime> object an IList.
5.the System.Array class, the base class of all array types, offers many static generic methods, such as AsReadOnly, BinarySearch, ConvertAll, Exists, Find, FindAll……


2.Generics Infrastructure
Generics were added to version 2.0 of the CLR, and it was a major task that required many people working for quite some time.
to make generics work, Microsoft had to do the following:
1.Create new Intermediate Language (IL) instructions that are aware of type arguments
2.Modify the format of existing metadata tables so that type names and methods with generic parameters could be expressed.
3.Modify the various programming languages (C#, Microsoft Visual Basic .NET, etc.) to support the new syntax, allowing developers to define and reference generic types and methods
4.Modify the compilers to emit the new IL instructions and the modified metadata format
5.Modify the just-in-time (JIT) compiler to process the new type-argument–aware IL instructions that produce the correct native code.
6.Create new reflection members so that developers can query types and members to determine if they have generic parameters. Also, new reflection emit members had to be defined so that developers could create generic type and method definitions at run time.
7.Modify the debugger to show and manipulate generic types, members, fields, and local variables.
8.Modify the Microsoft Visual Studio IntelliSense feature to show specific member prototypes when using a generic type or a method with a specific data type.
Open and Closed Types
how the CLR creates an internal data structure for each and every type in use by an application?
1. the CLR will create an internal type object for each of these.This applies to reference types (classes), value types (structs), interface types, and delegate types
These data structures are called type objects. Well, a type with generic type parameters is still considered a type
2.However, a type with generic type parameters is called an open type, and the CLR does not allow any instance of an open type to be constructed
3.the CLR allocates a type’s static fields inside the type object. So each closed type has its own static fields
In other words, if List<T> defined any static fields, these fields are not shared between a List<DateTime> and a List<String>;
4.if a generic type defines a static constructor, this constructor will execute once per closed type.
Sometimes people define a static constructor on a generic type to ensure that the type arguments will meet certain criteria.

5.The CLR has a feature called constraints that offers a better way for you to define a generic type indicating what type arguments are valid for it.
Unfortunately,constraints do not support the ability to limit a type argument to enumerated types only,which is why the previous example requires a static constructor to ensure that the type is an enumerated type.
how the CLR prevents an instance of an interface type from being constructed?
a type with generic type parameters is called an open type
1.When code references a generic type, it can specify a set of generic type arguments.
If actual data types are passed in for all of the type arguments, the type is called a closed type, and the CLR does allow instances of a closed type to be constructed.
2.However, it is possible for code referencing a generic type to leave some generic type arguments unspecified.
This creates a new open type object in the CLR, and instances of this type cannot be created.


the exception’s string message indicates that the type still contains some generic parameters.
the type names end with a backtick (`) followed by a number. The number indicates the type’s arity
Generic Types and Inheritance
1.A generic type is a type, and as such, it can be derived from any other type.
2.When you use a generic type and specify type arguments, you are defining a new type object in the CLR, and the new type object is derived from whatever type the generic type was derived from
In other words, because List<T> is derived from Object, List<String> and List<Guid> are also derived from Object.
Similarly, because DictionaryStringKey<TValue> is derived from Dictionary<String, TValue>, DictionaryStringKey<Guid> is also derived from Dictionary<String, Guid>.
3.specifying type arguments doesn’t have anything to do with inheritance hierarchies
示例:


1.the m_next field must refer to another node that has the same kind of data type in its m_data field.
This means that the linked list must contain nodes in which all data items are of the same type (or derived type).
2.if I use Node<Object> everywhere, but then I would lose compile-time type safety, and value types would get boxed.
3.So a better way to go would be to define a non-generic Node base class and then define a generic TypedNode class (using the Node class as a base class).
Now, can have a linked list in which each node can be of a specific data type (not Object), get compile-time type safety, and avoid the boxing of value types.


write code to create a linked list in which each node is a different data type
Generic Type Identity
1.Sometimes generic syntax confuses developers.
After all, there can be a lot of less-than (<) and greater-than (>) signs sprinkled throughout your source code, and this hurts readability
2.To improve syntax, some developers define a new non-generic class type that is derived from a generic type and that specifies all of the type arguments.
示例:
方式一:

方式二:有问题


(1)the code that creates a list can be rewritten more simply (without less-than and greater-than signs),making your source code easier to read
(2)but lose type identity and equivalence

sameType will be initialized to false
(2.1)because you are comparing two different type objects. This also means that a method prototyped as accepting a DateTimeList will not be able to have a List<DateTime> passed to it.
(2.2)However, a method prototyped as accepting a List<DateTime> can have a DateTimeList passed to it because DateTimeList is derived from List<DateTime>.
Programmers may become easily confused by all of this.
方式三:正确
C# does offer a way to use simplified syntax to refer to a generic closed type while not affecting type equivalence at all;
can use the good-old using directive at the top of your source code file

(1)the using directive is really just defining a symbol called DateTimeList.
As the code compiles, the compiler substitutes all occurrences of DateTimeList with System.Collections.Generic.List<System.DateTime>.
This just allows developers to use a simplified syntax without affecting the actual meaning of the code, and therefore, type identity and equivalence are maintained.

方式四:正确
use C#’s implicitly typed local variable feature, where the compiler infers the type of a method’s local variable from the type of the expression you are assigning to it

Code Explosion
how?
1.When a method that uses generic type parameters is JIT-compiled
the CLR takes the method’s IL,substitutes the specified type arguments, and then creates native code that is specific to that method operating on the specified data types.
This is exactly what you want and is one of the main features of generics.
2.However, there is a downside to this: the CLR keeps generating native code for every method/type combination.
This is referred to as code explosion. This can end up increasing the application’s working set substantially, thereby hurting performance
the CLR has some optimizations built into it to reduce code explosion
1.if a method is called for a particular type argument, and later, the method is called again using the same type argument, the CLR will compile the code for this method/type combination just once.
So if one assembly uses List<DateTime>, and a completely different assembly (loaded in the same AppDomain) also uses List<DateTime>, the CLR will compile the methods for List<DateTime> just once. This reduces code explosion substantially.
2.the CLR considers all reference type arguments to be identical, and so again, the code can be shared.
because all reference type arguments or variables are really just pointers (all 32 bits on a 32-bit Windows system and 64 bits on a 64-bit Windows system) to objects on the heap, and object pointers are all manipulated in the same way.
For example, the code compiled by the CLR for List<String>’s methods can be used for List<Stream>’s methods, because String and Stream are both reference types. In fact, for any reference type, the same code will be used
3.But if any type argument is a value type, the CLR must produce native code specifically for that value type.
The reason is because value types can vary in size.
And even if two value types are the same size (such as Int32 and UInt32, which are both 32 bits), the CLR still can’t share the code because different native CPU instructions can be used to manipulate these values.
3.Generic Interfaces
the ability to define generic reference and value types was the main feature of generics. However, it was critical for the CLR to also allow generic interfaces
benifit:
Without generic interfaces, any time you tried to manipulate a value type by using a non-generic interface (such as IComparable),boxing and a loss of compile-time type safety would happen again. This would severely limit the usefulness of generic types.
And so the CLR does support generic interfaces.
how?
1.A reference or value type can implement a generic interface by specifying type arguments
2.A reference or value type can implement a generic interface by leaving the type arguments unspecified



4.Generic Delegates
The CLR supports generic delegates
benifit:
1.to ensure that any type of object can be passed to a callback method in a type-safe way.
2.allow a value type instance to be passed to a callback method without any boxing
delegate :
1. is really just a class definition with four methods: a constructor, an Invoke method, a BeginInvoke method,and an EndInvoke method.
2.When you define a delegate type that specifies type parameters, the compiler defines the delegate class’s methods, and the type parameters are applied to any methods having parameters/return types of the specified type parameter.

compiling:

5.Delegate and Interface Contra-variant and Covariant Generic Type Arguments
Delegate
Each of a delegate’s generic type parameters can be marked as covariant or contra-variant.
benifit:
allows you to cast a variable of a generic delegate type to the same delegate type where the generic parameter types differ
A generic type parameter can be any one of the following:
1.Invariant
Meaning that the generic type parameter cannot be changed
2.Contra-variant
Meaning that the generic type parameter can change from a class to a class derived from it.
In C#, you indicate contra-variant generic type parameters with the in keyword.
Contra-variant generic type parameters can appear only in input positions such as a method’s argument.
3.Covariant
Meaning that the generic type argument can change from a class to one of its base classes.
In C#, you indicate covariant generic type parameters with the out keyword.
Covariant generic type parameters can appear only in output positions such as a method’s return
type.
how to use it?
1.

the generic type parameter T is marked with the in keyword, making it contra-variant; and the generic type parameter TResult is marked with the out keyword, making it covariant.
2.When using delegates that take generic arguments and return types.
it is recommended to always specify the in and out keywords for contra-variance and covariance whenever possible
because doing this has no ill effects and enables your delegate to be used in more scenarios.
示例:
if I have a variable declared as follows.

I can cast it to another Func type, where the generic type parameters are different.

Because you can pass a String to a method that wants an Object (because String is derived from Object), and because you can take the result of a method that returns an ArgumentException and treat it as an Exception (because Exception is a base class of ArgumentException), the code above compiles and is known at compile time to preserve type safety.
相关知识点:
1.Variance applies only if the compiler can verify that a reference conversion exists between types.
In other words, variance is not possible for value types because boxing would be required.
In my opinion, this restriction is what makes these variance features not that useful.
example:

can’t call it passing in a reference to a List<DateTime> object because a reference conversion doesn’t exist between the DateTime value type and Object even though DateTime is derived from Object.
solve this problem by declaring ProcessCollection as follows:add

2.the big benefit of ProcessCollection(IEnumerable<Object> collection) is that there is only one version of the JITted code.
However, with ProcessCollection<T>(IEnumerable<T>collection), there is also only one version of the JITted code shared by all Ts that are reference types.
You do get other versions of JITted code for Ts that are value types, but now you can at least call the method passing it a collection of value types.
3.variance is not allowed on a generic type parameter if an argument of that type is passed to a method by using the out or ref keyword

example:
causes the compiler to generate the following error message: Invalid variance: The type parameter 'T' must be invariantly valid on 'SomeDelegate<T>.Invoke(ref T)'. 'T' is contravariant.
4.why they must explicitly put in or out on generic type parameters?
interface
an interface with a covariant generic type parameter

Because T is covariant, it is possible to have the following code compile and run successfully

6.Generic Methods
7.Generics and Other Members
8.Verifiability and Constraints
12.Generics的更多相关文章
- python 各模块
01 关于本书 02 代码约定 03 关于例子 04 如何联系我们 1 核心模块 11 介绍 111 内建函数和异常 112 操作系统接口模块 113 类型支持模块 114 正则表达式 115 语言支 ...
- Python Standard Library
Python Standard Library "We'd like to pretend that 'Fredrik' is a role, but even hundreds of vo ...
- 在mybatis中写sql语句的一些体会
本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...
- JDK1.5新特性(六)……Generics
概述 Generics - This long-awaited enhancement to the type system allows a type or method to operate on ...
- Swift进阶 - 12个技巧
听说你已经学习Swift几个月了,有没有想更进一步成为Swift高手的想法?我这里有11招秘技,各位施主且听我慢慢道来,结个善缘. 1. 扩展(Extension) 任务: 求数字的平方. // 菜鸟 ...
- AndroidStudio — Error:Failed to resolve: junit:junit:4.12错误解决
原博客:http://blog.csdn.net/u013443865/article/details/50243193 最近使用AndroidStudio出现以下问题: 解决:打开app下的buil ...
- 读过MBA的CEO更自私?《哈佛商业评论》2016年第12期。4星
老牌管理杂志.每期都值得精度.本期我还是给4星. 以下是本书中的一些内容的摘抄: 1:他们发现在Airbnb上,如果客人姓名听起来像黑人,那么比名字像白人的客人的接受率会低16%.#45 2:对立组织 ...
- 12个小技巧,让你高效使用Eclipse
集成开发环境(IDE)让应用开发更加容易.它们强调语法,让你知道是否你存在编译错误,在众多的其他事情中允许你单步调试代码.像所有的IDE一 样,Eclipse也有快捷键和小工具,这些会让您感觉轻松许多 ...
- 第12章 Linux系统管理
1. 进程管理 1.1 进程查看 (1)进程简介 进程是正在执行的一个程序或命令(如ls命令也是一个进程),每个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源. (2)进程管理的作用 ...
随机推荐
- 【和小强学移动app测试2】移动终端app测试点归纳(持续更新)
以下所有测试最后必须在真机上完整的执行 1.安装.卸载测试 在真机上的以及通过91等第三方的安装与卸载 安装在手机上还是sd卡上 2.启动app测试 3.升级测试 数字签名.升级覆盖安装.下载后手 ...
- Servlet概念框架
以 Servlet 3.0 源代码为基础.Servlet 是 Javaweb 应用的基础框架,犹如孙子兵法之于作战指挥官,不可不知. 概念框架 机制: 事件 Event, 监听器 Listener 数 ...
- 关于oracle 11g 64位与 32位的 plsql、及其他32位应用程序共存的问题
因为 plsql 不支持 64位 oracle 客户端,所以plsql 必须使用 oracle 的 32位 instanclient 包. 解压缩后放一个目录,例如: D:\Oracle\insta ...
- asp显示多条记录的代码
asp显示多条记录的代码 仅供参考 <%for i=1 to RS.PageSize%> <% if RS.EOF then exit for end if %> <tr ...
- 介绍“Razor”— ASP.NET的一个新视图引擎
我的团队当前正在从事的工作之一就是为ASP.NET添加一个新的视图引擎. 一直以来,ASP.NET MVC都支持 “视图引擎”的概念—采用不同语法的模板的可插拔模块.当前ASP.NET MVC “默认 ...
- oracle 11g升级
手先需要下载oracle11g的补丁安装包,一般只有付费用户才能获取到该安装包,其他用户获取不到,那怎么办呢? 万能的互联网可以办到,可以用http://www.wangpansou.cn/所有其他用 ...
- Linux下命令行安装WebLogic 10.3.6
1.创建用户useradd weblogic;创建用户成功linux系统会自动创建一个和用户名相同的分组,并将该用户分到改组中.并会在/home路径下创建一个和用户名相同的路径,比如我们创建的webl ...
- Readonly和disabled的区别 display:none和visible:hidden的区别
怎样使input中的内容为只读,也就是说不让用户更改里面的内容. <input type="text" name="input1" value=" ...
- ecshop的几个小瑕疵
在安装Ecshop的时候,遇到两个问题: 1.Strict Standards: Non-static method cls_image::gd_version() should not be cal ...
- [ios][opengles]opengles在ios上的透明问题
关于透明,OpenGL/ES 中可以通过 blend (混色) 来简单实现,混色的基本原理就是把要绘制的物体的颜色与屏幕上已经绘制好的颜色以一定比例来混合,最后的颜色看上去就像半透明一样.要使用混合先 ...