12.Generics
benifit:
1.make developers extremely productive is code reuse, which is the ability toderive a class that inherits all of the capabilities of a base class.
The derived class can simply overridevirtual methods or add some new methods to customize the behavior of the base class to meet thedeveloper’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 referencetypes 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 accessto the algorithm’s source code.
With C++ templates, however, the algorithm’s source codemust 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 CLRunderstand this and ensure that only objects compatible with the specified data type are usedwith the algorithm.
Attempting to use an object of an incompatible type will result in eithera compiler error or a run-time exception being thrown.
In the example, attempting to pass aString 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 yoursource 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 todefine all of its members to work with the Object data type. If you wanted to use the algorithmwith value type instances, the CLR had to box the value type instance prior to callingthe members of the algorithm.boxing causes memory allocations on the managed heap, which causes more frequentgarbage collections, which, in turn, hurt an application’s performance.
Because a genericalgorithm 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, becausecasts are not necessary (see the previous bullet), the CLR doesn’t have to check the type safetyof the attempted cast, and this results in faster code too.
using the generic List algorithm with the Int32 type is much fasterthan using the non-generic ArrayList algorithm with Int32.becauseusing a value type (Int32)with ArrayList causes a lot of boxing operations to occur
using reference types is not as momentous.the times andnumber of garbage collections are about the same. So it doesn’t appear that the generic List algorithmis of any benefit here.
However, keep in mind that when using a generic algorithm, you also getcleaner 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.
其他知識(shí):
1.Microsoft’s design guidelines state that generic parameter variables should eitherbe called T or at least start with an uppercase T (as in TKey and TValue).
The uppercase Tstands for type, just as an uppercase I stands for interface (as in IComparable).
2.the CLR generates native code for each method thefirst time the method is called for a particular data type. This will increase an application’sworking set size, which will hurt performance
1.Generics in the Framework Class Library
1.the most obvious use.the FCL defines severalgeneric 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 discouragesuse of the non-generic collection classes
(1)get the type safety, cleaner code, and better performance
(2)have a better objectmodel.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 collectionscan implement interfaces that the collection classes use for operations such as sorting andsearching.
The FCL ships with many generic interface definitions so that the benefits of generics canbe realized when working with interfaces as well.
The commonly used interfaces are contained in theSystem.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> objectan IList.
5.the System.Array class, the base class of all array types, offers manystatic 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 peopleworking 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 genericparameters could be expressed.
3.Modify the various programming languages (C#, Microsoft Visual Basic .NET, etc.) to supportthe 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 instructionsthat produce the correct native code.
6.Create new reflection members so that developers can query types and members to determineif they have generic parameters. Also, new reflection emit members had to be defined sothat 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 prototypeswhen using a generic type or a method with a specific data type.
Open and Closed Types
how the CLR creates an internal data structurefor each and every type in use by an application?
1.the CLR will create an internaltype object for each of these.This applies to reference types (classes), value types (structs), interfacetypes, 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, andthe 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 otherwords, 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 definesa static constructor, this constructor will execute once per closedtype.
Sometimes people define a static constructor on a generic type to ensure that the type argumentswill meet certain criteria.
5.The CLR has a feature called constraints that offers a better way for you to define a generic typeindicating 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 enumeratedtype.
how the CLR preventsan 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 datatypes are passed in for all of the type arguments, the type is called a closed type, and the CLR doesallow instances of a closed type to be constructed.
2.However, it is possible for code referencing a generictype to leave some generic type arguments unspecified.
This creates a new open type object inthe CLR, and instances of this type cannot be created.
the exception’s string message indicatesthat the type still contains some generic parameters.
the type names end with a backtick (`) followed by a number. Thenumber 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 generictype and specify type arguments, you are defining a new type object in the CLR, and the new typeobject is derived from whatever type the generic type was derived from
In other words, becauseList<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 samekind of data type in its m_data field.
This means that the linked list must contain nodes in which alldata items are of the same type (or derived type).
2.if I use Node<Object> everywhere, but then I would losecompile-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 genericTypedNode class (using the Node class as a base class).
Now, can have a linked list in which eachnode can be of a specific data type (not Object), get compile-time type safety, and avoid the boxingof 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 (<) andgreater-than (>) signs sprinkled throughout your source code, and this hurts readability
2.To improvesyntax, some developers define a new non-generic class type that is derived from a generic type andthat specifies all of the type arguments.
示例:
方式一:
方式二:有問題
(1)the code that creates a list can be rewritten more simply (without less-than and greater-thansigns),making yoursource code easier to read
(2)butlose type identity and equivalence
sameType will be initialized to false
(2.1)because you are comparingtwo different type objects. This also means that a method prototyped as accepting a DateTimeListwill not be able to have a List<DateTime> passed to it.
(2.2)However, a method prototyped as acceptinga List<DateTime> can have a DateTimeList passed to it because DateTimeList is derived fromList<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 notaffecting type equivalence at all;
can use the good-old using directive at the top of your sourcecode file
(1)the using directive is really just defining a symbol called DateTimeList.
As the codecompiles, the compiler substitutes all occurrences of DateTimeList with System.Collections.Generic.List<System.DateTime>.
This just allows developers to use a simplified syntax withoutaffecting the actual meaning of the code, and therefore, type identity and equivalence are maintained.
方式四:正確
use C#’s implicitly typed local variable feature, where the compilerinfers 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 methodoperating on the specified data types.
This is exactly what you want and is one of the main featuresof generics.
2.However, there is a downside to this: the CLR keeps generating native code for everymethod/type combination.
This is referred to as code explosion. This can end up increasing the application’sworking set substantially, thereby hurting performance
the CLR has some optimizations built into it to reduce code explosion
1.if amethod is called for a particular type argument, and later, the method is called again using the sametype argument, the CLR will compile the code for this method/type combination just once.
So if oneassembly 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> justonce. 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-bitWindows system and 64 bits on a 64-bit Windows system) to objects on the heap, and object pointersare all manipulated in the same way.
For example, the code compiled by the CLR for List<String>’smethods can be used for List<Stream>’s methods, because String and Stream are both referencetypes. 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 thatvalue type.
The reason is because value types can vary in size.
And even if two value types are thesame size (such as Int32 and UInt32, which are both 32 bits), the CLR still can’t share the code becausedifferent 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, anytime 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 theusefulness of generic types.
And so the CLR does support generic interfaces.
how?
1.A reference or value typecan implement a generic interface by specifying type arguments
2.A reference or valuetype can implement a genericinterface 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 callbackmethod in a type-safe way.
2.allow a value type instance to be passedto a callback method without any boxing
delegate :
1. is reallyjust 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, thecompiler defines the delegate class’s methods, and the type parameters are applied to any methodshaving parameters/return types of the specified type parameter.
compiling:
5.Delegate and Interface Contra-variant andCovariant 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 thegeneric 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 aclass derived from it.
In C#, you indicate contra-variant generic type parameters with the inkeyword.
Contra-variant generic type parameters can appear only in input positions such as amethod’s argument.
3.Covariant
Meaning that the generic type argument can change from a class to one of itsbase classes.
In C#, you indicate covariant generic type parameters with the out keyword.
Covariantgeneric 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; andthe 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 alwaysspecify the in and out keywords for contra-variance and covariance whenever possible
because doingthis 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 (becauseString is derived from Object), and because you can take the result of a method that returnsan ArgumentExceptionand treat it as an Exception (because Exception is a base class ofArgumentException),the code above compiles and is known at compile time to preserve typesafety.
相關(guān)知識(shí)點(diǎn):
1.Variance applies only if the compiler can verify that a reference conversion exists betweentypes.
In other words, variance is not possible for value types because boxing wouldbe required.
In my opinion, this restriction is what makes these variance features not thatuseful.
example:
can’t call it passing in a reference to a List<DateTime> object because a reference conversiondoesn’t exist between the DateTime value type and Object even though DateTimeis derived from Object.
solve this problem by declaring ProcessCollection as follows:add
2.the big benefit of ProcessCollection(IEnumerable<Object> collection) is thatthere 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 byall Ts that are reference types.
You do get other versions of JITted code for Ts that are valuetypes, 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 ispassed 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 generictype 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
總結(jié)
以上是生活随笔為你收集整理的12.Generics的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java安卓的xml布局,android
- 下一篇: 为什么要使用双亲委派机制?