Since the launch of the net framework in version 2.0, Generic (Generic) has been widely praised. It does not have to suffer performance loss like the object type because of "unpacking" or "Packing". At the same time, it can detect in real time whether the incoming or outgoing types meet specific conditions in the compilation syntax detection phase.
But "Gold is bare and nobody is perfect"-while we enjoy these happy programming, uncertainty of the generic type also brings a significant problem-operators cannot be reloaded. For example, what should I do if I want to write a function (a general selection sorting algorithm using generic T? If you simply use such code (C # is as follows ):
Copy codeThe Code is as follows:
// Improved Sorting Algorithm from small to large
Public static void Sort <T> (T [] array)
{
Bool flag = false; // whether the flag has been sorted
For (int I = 0; I <array. Length-1; ++ I)
{
Flag = false; // each time it is assumed that the data has been sorted and no sort is required.
For (int j = I + 1; I <array. Length; ++ j)
{
If (array [I]> array [j])
{
Int temp = array [I];
Array [I] = array [j];
Array [j] = templ
Flag = true; // sorted
}
}
If (! Flag)
{
Break;
}
}
}
After compilation, you will soon find prompts such as "operator"> "cannot act on T.
Why? We know that Operator Overloading is defined for all types that can be greater than or less than the comparison. A general class must be defined for this purpose before comparison can be made. Otherwise, an error occurs because the comparison is not known if the class is greater than or less than the number (or other operators. So what type does the generic model know beforehand? The compiler checker naturally cannot infer that the type that you dynamically pass in during runtime must implement Operator overloading. If you strictly check the syntax, an error is reported.
What should we do? It is required that the generic T must implement the comparator (the mandatory T must implement the IComparable or similar interface ).
Copy codeThe Code is as follows:
Public static void Sort <T> (T [] array) where T: IComparable
{
Bool flag = false; // whether the flag has been sorted
For (int I = 0; I <array. Length-1; ++ I)
{
Flag = false; // each time it is assumed that the data has been sorted and no sort is required.
For (int j = I + 1; I <array. Length; ++ j)
{
If (array [I]. Compare (array [j])> 0)
{
Int temp = array [I];
Array [I] = array [j];
Array [j] = templ
Flag = true; // sorted
}
}
If (! Flag)
{
Break;
}
}
}
Once the generic type is restricted, the generic type must be the class that implements this interface and must have this method (the Compare method returns the int type of the result, if the value is greater than 0, the previous number is greater than the next one ).
Of course, the Microsoft class library has a Comparer static class, has implemented this interface can be directly compared (http://msdn.microsoft.com/zh-cn/library/system.collections.comparer.comparer.aspx), so we can also choose to directly use the Compare method in this static class to get the result.
[Example 2] implement a common "+" -- that is, if the input string is passed in, the character is automatically spliced according to the string; if the input is another basic type (int, double, etc ), returns the result of adding.
Microsoft does not have a pre-defined "+" interface, so it cannot be used directly (of course, you can define a custom interface as required ). Let's change the method -- use the expression tree (C # code is as follows ):
Copy codeThe Code is as follows:
Public static T Add <T> (T a, T B)
{
Expression left = Expression. Constant ();
Expression right = Expression. Constant (B );
Type t = typeof (T );
Expression value;
If (t = typeof (string ))
{
Value = Expression. Constant (a. ToString () + B. ToString ());
}
Else
{
Value = Expression. Add (left, right );
}
Expression <Func <T> addExp = Expression. Lambda <Func <T> (value );
Func <T> addFunc = addExp. Compile ();
Return addFunc ();
}
Dynamically judge whether T is a string or another basic type. Then, call different methods to form an Expression Tree, dynamically compile it into a Func expression, and return the result.