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)进程管理的作用 ...
随机推荐
- HAVING用法详解
HAVING 子句对 GROUP BY 子句设置条件的方式与 WHERE 和 SELECT 的交互方式类似.WHERE 搜索条件在进行分组操作之前应用:而 HAVING 搜索条件在进行分组操作之后应用 ...
- Openstack的error僵尸实例的解决办法
在我们对集群环境进行各种调整的情况下,很容易产生一些僵尸实例. 僵尸实例主要是没有该主机,但是在dashboard上,数据库中存在,解决办法网络上有的人给出了繁杂的修改数据库的方法,其实按照下面的命令 ...
- AMD机制与cMD的区别和概念简要介绍
1.http://www.cnblogs.com/dojo-lzz/p/4707725.html 2.http://blog.chinaunix.net/uid-26672038-id-4112229 ...
- 【MFC三天一个游戏】之 局域网黑白棋
欢迎加入我们的QQ群,无论你是否工作,学生,只要有c / vc / c++ 编程经验,就来吧!158427611 花了三天上班时间,妈的上班写就是不能静下心来,擦,要防BOSS巡山.... 以前也写过 ...
- COM编程之四 引用计数
[1]客户为什么不应直接控制组件的生命期? 假设一个组件A正在使用另一个组件B,可想组件A(客户)代码中肯定有若干个指向组件B接口的指针. 那么这种情况下,当使用完一个接口而仍然在使用另一个接口时,是 ...
- NEON在Android中的使用举例【转】
转自:http://blog.csdn.net/fengbingchun/article/details/37766607 版权声明:本文为博主原创文章,未经博主允许不得转载. 1. 打开Eclip ...
- Composer使用中常见的问题
安装了Composer后,运行 composer --version ,查看Composer的版本号.如果出现下面的提示,那么软件安装成功. Composer version 1.2.0 2016-0 ...
- 删除ecshop云服务及授权关于官方等信息
一.删除[云服务中心] 删除/admin/cloud.php 删除/admin/templates/menu.htm中以下代码 Ajax.call('cloud.php?is_ajax=1>ac ...
- expect语法
沙河西ftp上传,使用了expect语言的脚本. 我们经常会遇到一些需要与服务器程序打交道的场景,比如,从登陆某个服务器,然后进行某项工作.这很平常,但是如果把这个工作自动化进行,你就需要一个程序能自 ...
- openlayers 学习笔记一
1. 创建地图,加载控件 var map = new OpenLayers.Map("map", { projection: new OpenLayers.Projection(& ...