Parameter name: request
In C# there is two types of mechanism for writing code that is reusable across different type.
1)Inheritance
2)Generic.
Inheritance express reusability across base type,while generic express reusability with a template that contains placeholder.
Mainly Generics used for type safety and reducing casting and boxing.
Now first glance on Generic Types.
A generic type declares generic parameters—placeholder types to be filled in by the consumer of the generic type, who will supply the generic arguments. Here is a generic type Stack
public class Stack
{
int position;
T[] data = new T[100];
public void Push (T obj) { data[position++] = obj; }
public T Pop() { return data[--position]; }
}
We can use Stack Stack Technically, we say that Stack Why generics exist? Different types of generic code that is reusable for writing exist. Let's say we need a stack of integers, but we did not have normal type. All the necessary elements for a solution (eg, IntStack, StringStack, etc.) Clearly, this type of code duplication would cause quite a different version of the class will hardcode. Another solution is to write a stack object by using the element type as would be generalized: An ObjectStack, however, wouldn't work as well as a hardcoded IntStack for specifically stacking integers. Specifically, an ObjectStack would require boxing and downcasting that could not be checked at compile time: stack.Push ("s"); // Wrong type, but no error! What we need is both a general implementation of a stack that works for all element types, and a way to easily specialize that stack to a specific element type for increased type safety and reduced casting and boxing. Generics give us precisely this, by allowing us to parameterize the element type. Stack has the benefits of both ObjectStack and IntStack. Like ObjectStack, Stack is written once to work generally across all types. Like IntStack, Stack is specialized for a particular type—the beauty is that this type is T, which we substitute on the fly. A generic method declares generic parameters within the signature of a method. With generic methods, many fundamental algorithms can be implemented in only a general-purpose way. Here is a generic method that swaps two values of any type: Swap Generally, there is no need to supply type parameters to a generic method, because the compiler can implicitly infer the type. If there is ambiguity, generic methods can be called with the type parameters as follows: Within a generic type, a method is not classed as generic unless it introduces generic parameters (with the angle bracket syntax). The Pop method in our generic stack merely uses the type's existing generic parameter, T, and is not classed as a generic method. Methods and types are the only constructs that can introduce generic parameters. Properties, indexers, events, fields, methods, operators, and so on cannot declare generic parameters, although they can partake in any generic parameters already declared by their enclosing type. In our generic stack example, for instance, we could write an indexer that returns a generic item: Generic parameters can be introduced in the declaration of classes, structs, interfaces, delegates (see the upcoming "Delegates" section), and methods. Other constructs, such as properties, cannot introduce a generic parameter, but can use a generic parameter. For example, the property Value uses T: A generic type or method can have multiple parameters. For example: class Dictionary To instantiate: Dictionary Generic type names and method names can be overloaded as long as the number of generic parameters is different. For example, the following two type names do not conflict: The typeof operator requires specifying the number of parameters when asking for the type of an open type, as follows: Type a1 = typeof(A<>); Here is an example of asking for the type of a closed type: Type a3 = typeof(A The default keyword can be used to get the default value given a generic type argument. The default value for a reference type is null, and the default value for a value type is the result of bitwise-zeroing the value type's fields: By default, a generic parameter can be substituted with any type whatsoever. Constraints can be applied to a generic parameter to require more specific type arguments. These are the possible constraints: where T : base-class // Base class constraint In the following example, GenericClass class GenericClass Constraints can be applied wherever generic parameters are defined, in both methods and type definitions. A base class constaint or interface constraint specifies that the type parameter must subclass or implement a particular class or interface. This allows instances of that type to be implicitly cast to that class or interface. For example, suppose we want to write a generic Max method that returns the maximum of two values. We can take advantage of the generic interface defined in the System namespace IComparable CompareTo returns a positive number if other is greater than this. Using this interface as a constraint, we can write a Max method as follows (to avoid distraction, null checking is omitted): The Max method can accept arguments of any type implementing IComparable int z = Max (5, 10); // 10 The class constraint and struct constraint simply specify that T must be a class or a struct. A great example of the struct constraint is the System.Nullable struct Nullable The parameterless constructor constraint requires T to have a public parameterless constructor. If this constraint is defined, you can call new() on T: The naked type constraint requires one generic parameter to derive from another generic parameter. In this example, the method FilteredStack returns another Stack, containing only the subset of elements where the generic parameter T is of the generic parameter U: class Stack Generic types are not covariant. This means that even if B can be cast to A, T cannot be cast to T. For example, suppose Animal and Bear are defined as follows: class Animal {} The following is illegal: // compile-time error Lack of covariance can hinder reusability. Suppose, for instance, we wanted to write a method to Wash a stack of animals: Calling Wash with a stack of bears would generate a compile-time error. The workaround is to redefine the Wash method with a constraint: We can now call Wash as follows: Stack Or the subclass can close the generic type parameters with a concrete type: class IntStack : Stack A subclass can also introduce fresh generic arguments: class Single public class Balloon : IEquatable public bool Equals (Balloon b) Static data is unique for each closed type: class Test You can instantiate and populate a generic collection in a single step, as follows: using System.Collections.Generic; The compiler translates this to: using System.Collections.Generic; List This requires that the collection implements the ICollection
Stack
stack. Push(5);
stack. Push(10);
int x = stack.Pop(); // x is 10
int y = stack.Pop(); // y is 5
public class ###
{
int position;
int[] data;
public void Push (int obj) { data[position++] = obj; }
public int Pop() { return data[--position];}
}
public class ObjectStack
{
int position;
object[] data = new object[10];
public void Push (object obj){data[position++] = obj;}
public object Pop() { return data[--position];}
}
// Suppose we just want to store integers here:
ObjectStack stack = new ObjectStack();
int i = (int)stack.Pop(); // Downcast - runtime error
static void Swap
{
T temp = a; a = b; b = temp;
}
int x = 5, y = 10;
Swap (ref x, ref y);
Swap
public T this [int index] { get {return data [index];} }
public struct Nullable
{
public T Value {get;}
}
var myDic = new Dictionary
class A
class Atypeof and Generics
class A
class A
...
Type a2 = typeof(A<,>);
static void Zap
{
for (int i = 0; i < array.Length; i++)
array[i] = default(T);
}
where T : interface // Interface constraint
where T: class // Class constraint
where T : struct // Struct constraint
where T : new() // Parameterless constructor
// constraint
where U : T // Naked type constraint
class SomeClass {}
interface Interface1 {}
public interface IComparable
{
int CompareTo (T other);
}
static T Max
{
return a.CompareTo (b) > 0 ? a : b;
}
string last = Max ("ant", "zoo"); // zoo
static void Initialize
{
for (int i = 0; i < array.Length; i++)
array[i] = new T();
}
{
Stack FilteredStack() where U : T {...}
}
class Bear : Animal {}
Stack
Stack
public class ZooCleaner
{
public static void Wash (Stack
}
public class ZooCleaner
{
public static void Wash
where T : Animal {}
}
ZooCleaner.Wash (bears);
A generic class can be subclassed just like a nongeneric class. The subclass can leave the base class's generic parameters open, as in the following example:
class Stack
class SpecialStack
class Double
A type can name itself as the concrete type when closing a generic argument:
public interface IEquatable
{
string color;
int cc;
{
if (b == null) return false;
return b.color == color && b.cc == cc;
}
}
class Bob
{
static void Main()
{
Console.WriteLine (++Bob
Console.WriteLine (++Bob
Console.WriteLine (++Bob
Console.WriteLine (++Bob
...
List
...
list.Add (1); list.Add (2); list.Add (3);
No comments:
Post a Comment