C # 2.0 new features (top)

Source: Internet
Author: User
Tags emit

C # 2.0 new feature 1. Generic 1.1 Generics Introduction

Generic classes and generic methods are both reusable, type safe, and efficient, which are not available for non-generic and non-generic methods. Generics are typically used in collections and in methods that run on collections. The. NET Framework version 2.0 class library provides a new namespace, System.Collections.Generic, that contains several new generic-based collection classes. It is recommended that all applications for version 2.0 use the new generic collection class instead of the old non-generic collection classes, such as ArrayList. For more information, see Generics in the. NET Framework Class Library (C # Programming Guide).

1.2 Benefits of Generics

1. Avoid forced boxing and unpacking operations during collection operations to improve performance.

2. Strongly typed data type checks to prevent data compilation from being passed, but the runtime can detect data type errors.

1.3 Generic type parameters

In a generic type or method definition, a type parameter is a placeholder for a specific type specified by the client when instantiating a variable of a generic type. Generic classes, such as those listed in the generic Introduction (C # Programming Guide), cannot be used in this way, because it is not really a type, but rather a blueprint for a type.-- genericlist<t> To use genericlist<t>, client code must declare and instantiate a constructed type by specifying the type parameter in angle brackets. The type parameter for this particular class can be any type recognized by the compiler. You can create any number of constructed type instances, each with a different type parameter, as follows:

Genericlist<float> List1 = new genericlist<float> (); genericlist<exampleclass> list2 = new genericlist<exampleclass> (); genericlist<examplestruct> list3 = new genericlist<examplestruct> ();

In each genericlist<t> instance, each T that appears in the class is replaced with the corresponding type parameter at run time. In this way, we use a class definition to create three independent types of valid objects of type safety. For more information about how the CLR performs this substitution, see Generics in the Runtime (C # Programming Guide).

T: For a value type, the collection creates an instance of a different value type, using the same instance for a collection of value types of the same type.

T: For reference types, when the collection is first used, the instance is created, and the different reference types use the same instance.

1.4 Constraints on Type parameters

When you define a generic class, you can impose restrictions on the type types that client code can use for type parameters when instantiating a class. If the client code attempts to instantiate a class with a type that is not allowed by a constraint, a compile-time error occurs. These restrictions are called constraints. Constraints are specified using the where context keyword. The following table lists the six types of constraints:

Constraints Description

T: Structure

The type parameter must be a value type. You can specify any value type other than Nullable. For more information, see Working with Nullable Types (C # Programming Guide).

T: Class

The type parameter must be a reference type, including any class, interface, delegate, or array type.

T:new ()

The type parameter must have a public constructor with no parameters. When used with other constraints, thenew () constraint must be specified last.

t:< base class name >

The type parameter must be the specified base class or derive from the specified base class.

t:< Interface Name >

The type parameter must be the specified interface or implement the specified interface. You can specify multiple interface constraints. The constraint interface can also be generic.

T:u

The type parameter provided for T must be either a parameter supplied for u or a parameter derived from U. This is called a bare type constraint.

 1.5 generic class

Generic class encapsulation is not an operation specific to a specific data type. Generic classes are most commonly used in collections, such as linked lists, hash tables, stacks, queues, trees, and so on, where operations such as adding and removing items from a collection are performed in substantially the same way regardless of the type of data being stored.

In general, the process of creating a generic class is to start with an existing concrete class, changing each type to a type parameter one at a to achieve the best balance of generalization and usability. When you create your own generic classes, you need to pay special attention to the following things:

      • What types are generalized to type parameters.

        The general rule is that the more types you can parameterize, the more flexible the code becomes and the better the reusability. However, too much generalization can make it difficult for other developers to read or understand the code.

      • If there are constraints, what constraints should be applied to the type parameters (see constraints on type parameters (C # Programming Guide)).

        A useful rule is to apply as many constraints as possible, but still allow you to handle types that need to be processed. For example, if you know that your generic class is only for reference types, apply a class constraint. This prevents your class from being used unexpectedly for value types, and allows you to use the as operator for T and check for null values.

      • Whether to decompose the generic behavior into base classes and subclasses.

        Because generic classes can be used as base classes, the design considerations that apply here are the same as for non-generic classes. For rules that inherit from a generic base class, see the following.

      • Whether to implement one or more generic interfaces.

        For example, if you design a class that will be used to create an item in a generic-based collection, you might need to implement an interface, such as icomparable<t>, where T is the type of your class.

1.6 Generic interface

It is often useful to define an interface for a generic collection class or a generic class that represents an item in a collection. For generic classes, it is advisable to use a generic interface, such as using icomparable<t> instead of IComparable, to avoid boxing and unboxing of value types. The. NET Framework 2.0 Class library defines several new generic interfaces for System.Collections.Generic the new collection class in the namespace.

When you specify an interface as a constraint on a type parameter, you can only use types that implement this interface. The following code example shows the sortedlist<t> class derived from the genericlist<t> class. For more information, see Introduction to Generics (C # Programming Guide). sortedlist<t> added a constraint where t:icomparable<t>. This will enable the Bubblesort method in sortedlist<t> to use the generic CompareTo method for list elements.

1.7 Generic methods

A generic method can also use constraints, and the T in a generic method avoids the same type substitution as in a generic class.

1.8 Generics and Arrays

In C # 2.0, a one-dimensional array with a lower bound of zero automatically implements Ilist<t>. This enables you to create generic methods that enable you to iterate through the array and other collection types using the same code. This technique is primarily useful for reading data from a collection. The ilist<t> interface cannot be used to add or remove elements from an array, and an exception will be thrown if an attempt is made to invoke the ilist<t> method In this context (such as the RemoveAt of arrays).

1.9 Generic Delegates

A delegate can define its own type parameters. Code that references a generic delegate can specify a type parameter to create a constructed type that has been closed, just like instantiating a generic class or invoking a generic method

1.10 Default keywords in generic code

One problem that arises in generic classes and generic methods is how to assign a default value to a parameterized type T when the following conditions are not known in advance:

      • T is a reference type or a value type.

      • If T is a value type, then it is numeric or structure.

Given a variable t of the parameterized type T, the statement t = NULL is valid only if T is a reference type, and the statement t = 0 is used only when T is a numeric type and not a struct. The solution is to use the default keyword, which returns null for reference types and zero for numeric types. For structs, this keyword returns each struct member initialized to zero or null, depending on whether the structure is a value type or a reference type. The following example from the genericlist<t> class shows how to use the default keyword. For more information, see Generic Overview.

1.11 Generics in the run-the-Library

When a generic type or method is compiled into Microsoft intermediate language (MSIL), it contains metadata that identifies it as having a type parameter. The use of MSIL for generic types differs depending on whether the supplied type parameter is a value type or a reference type.

For value types: The first time a generic type is constructed with a value type as a parameter, the runtime creates a specialized generic type, substituting the supplied parameters into the appropriate location in the MSIL. For each unique value type used as a parameter, a specialized generic type is created once.

For reference types: generics work in slightly different ways. The first time a generic type is constructed with any reference type, the runtime creates a specialized generic type, replacing the parameters in the MSIL with the object reference. Then, each time a constructed type is instantiated with a reference type as a parameter, the runtime reuses the private version of the previously created generic type, regardless of the specific type of the reference type. This is possible because all references are of the same size.

In addition, when you instantiate a generic C # class with a type parameter, whether it is a value type or a reference type, you can query it using reflection at run time, and you can determine its actual type and type parameters.

1.12 generics in the. NET Framework class Library

The. NET Framework version 2.0 class library provides a new namespace, System.Collections.Generic, which includes several ready-to-use generic collection classes and associated interfaces. Other namespaces, such as system, also provide new generic interfaces, such as icomparable<t>. These classes and interfaces are more efficient and type-safe than the non-generic collection classes provided by earlier versions of the. NET Framework. Before you design and implement your own custom collection classes, consider whether you can use the classes provided by the base Class library, or whether you can derive from the classes provided by the base Class library.

1.13 Generics and reflection

Because the common language runtime (CLR) is able to access generic type information at run time, you can use reflection to get information about generic types in the same way as for non-generic types. For more information, see Generics in the Runtime (C # Programming Guide).

In the. NET Framework 2.0, the type class adds several new members to enable run-time information for generic types. For more information about how to use these methods and properties, see the documentation for these classes. The System.Reflection.Emit namespace also contains new members that support generics. See how to: Define a generic type with reflection emit.

1.14 Generics and properties

A property can be applied to a generic type in the same way as it is applied to a non-generic type. For more information about applying properties, see Properties (C # Programming Guide).

Custom properties only allow referencing open generic types (generic types that do not provide type parameters) and enclosing constructed generic types (parameters are supplied for all type parameters).

2. iterators

Iterators are a new feature in C # 2.0. Iterators are methods, get accessors, or operators that enable you to support foreach iterations in a class or struct without having to implement the entire IEnumerable interface. You only need to provide an iterator to traverse the data structure in the class. When the compiler detects an iterator, it automatically generates the current,MoveNext , and Dispose of the IEnumerable or Ienumerable<t> interface method.

2.1 Iterators Overview

1. Iterators are a piece of code that can return an ordered sequence of values of the same type.

2. An iterator can be used as the code body for a method, operator, or get accessor.

3. The iterator code returns each element in turn using the yield return statement. yield break terminates the iteration. For more information, see yield.

4. You can implement multiple iterators in a class. Each iterator must have a unique name like any class member, and can be called by client code in a foreach statement, as follows:foreach (int x in Sampleclass.iterator2) {}

5. The return type of the iterator must be IEnumerable, IEnumerator,IEnumerable<T> or ienumerator<t>.

The yield keyword is used to specify the value returned. When the yield return statement is reached, the current position is saved. The next time the iterator is called, execution will start again from this location.

Iterators are particularly useful for collection classes, which provide an easy way to iterate over infrequently used data structures, such as binary trees.

2.2 Using Iterators

The most common way to create iterators is to implement the GetEnumerator method on the IEnumerable interface.

    The presence of the GetEnumerator method makes the type an enumerable type and allows the use of a foreach statement.

    The foreach statement calls Listclass.getenumerator () and uses the returned enumerator to iterate through the values. For an example of how to create a generic iterator that returns a IEnumerator interface, see How to: Create an iterator block for a generic list (C # Programming Guide).

You can also use named Iterators to support iterating through the same data collection in different ways. For example, you can provide an iterator that returns an element in ascending order, while providing another iterator that returns the element in descending. Iterators can also have parameters that allow the client to control all or part of the iterative behavior.

You can use multiple yield statements in the same iterator.

In each subsequent iteration of the foreach loop (or a direct call to Ienumerator.movenext ), the next iterator code body begins after a yield statement, and continue to the next statement until the end of the iterator body is reached or the yield break statement is encountered.

3. Partial Classes

You can split the definition of a class, struct, or interface into two or more source files. Each source file contains part of the class definition, and all parts are combined when the application is compiled. You need to split the classification definition in the following situations:

When working with large projects, having a class spread across separate files allows multiple programmers to process the class at the same time.

When you use an automatically generated source, you can add code to the class without recreating the source files. Visual Studio uses this method when creating Windows forms, Web service wrapper code, and so on. You can create code that uses these classes without having to edit the files created by Visual Studio.

To split a classification definition, use the partial keyword modifier

4. Nullable types

Nullable types have the following characteristics:

1. A nullable type represents a value type variable that can be assigned a value of null . You cannot create a nullable type based on a reference type. (The reference type already supports null values.) )。

2. Syntax T? is a shorthand for system.nullable<t>, where t is a value type. These two forms are interchangeable.

3. Assigning a value to a nullable type is the same as assigning a value to a generic value type, such as int? x = ten; Or double? d = 4.108;.

4. If the value of the underlying type is null, use the System.Nullable.GetValueOrDefault property to return the value or default value assigned to the underlying type, such as int j = X.getvalueordefault ( );

5. Use the HasValue and value read-only properties to test if null and retrieve values, such as if (x.hasvalue) j = x.value;

6. Use the ?? operator to assign a default value, and the nullable type with the current value of NULL is assigned to a non-null type when the default value is applied, such as int? x = null; int y = x??-1;.

7. The use of nested nullable types is not allowed. The following line will not be compiled:nullable<nullable<int>> N;

5. Anonymous Methods

In the C # version prior to 2.0, the only way to declare a delegate was to use a named method. C # 2.0 introduces an anonymous method.

If you use anonymous methods, you do not have to create a separate method, thus reducing the coding overhead required to instantiate a delegate.

6. Namespace alias qualifier

The namespace alias qualifier (::) is used to find identifiers. It is usually placed between two identifiers, for example:

Global::system.console.writeline ("Hello World");

The namespace alias qualifier can be global. This invokes the lookup in the global namespace, not the alias namespace

7. Static class and Static class members

Static classes and class members are used to create data and functions that can be accessed without creating an instance of the class.

Static class members can be used to detach data and behaviors that are independent of any object identity: No matter what changes are made to the object, the data and functions do not change. Static classes can be used when there is no data or behavior in the class that depends on the identity of the object.

7.1Static Class

A class can be declared as static to indicate that it contains only static members. You cannot use the New keyword to create an instance of a static class. Static classes are loaded automatically by the. NET Framework Common Language Runtime (CLR) when the program or namespace containing the class is loaded.

Use static classes to include methods that are not associated with a particular object. For example, it is a common requirement to create a set of methods that do not manipulate instance data and are not associated with specific objects in your code. You should use static classes to include those methods.

The main functions of static classes are as follows:

1. They contain only static members.

2. They cannot be instantiated.

3. They are sealed.

4. They cannot contain instance constructors (C # Programming Guide).

Therefore, creating a static class is roughly the same as creating a class that contains only static members and private constructors. The private constructor prevents the class from being instantiated.

The advantage of using static classes is that the compiler is able to perform checks to ensure that instance members are not accidentally added. The compiler will guarantee that this class will not be created for real profit.

Static classes are sealed and therefore cannot be inherited. A static class cannot contain constructors, but you can still declare a static constructor to assign an initial value or set a static state. For more information, see Static Constructors (C # Programming Guide).

7.2 static members

Even if you do not create an instance of the class, you can call a static method, field, property, or event in the class. If you create any instances of the class, you cannot use instances to access static members. There is only one copy of static fields and events, and static methods and properties can only access static fields and static events. Static members are typically used to represent data or calculations that do not change with the state of the object; For example, a math library might contain static methods for calculating sine and cosine.

Declare static class members by using the static keyword before the return type of a member

C # 2.0 new features (top)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.