C # advanced programming Chapter 6 array,
In order to solve a large number of elements of the same type, the arrays are generated. Arrays are a collection of objects with certain order relationships. One-dimensional arrays can be seen as linear tables with fixed length. On the contrary, an array of n can be seen as a linear table extension. From the storage structure, the array is a continuous storage space. Now let's look at the array in C:
1. Normal Array
In C #, common Arrays can be classified into one-dimensional arrays, multi-dimensional arrays, and sawtooth arrays.
<1> one-dimensional array
Now let's take a look at the Declaration syntax of the one-dimensional array:
Type [] variable name;
Now let's take a look at array initialization. There are four initialization methods in C:
// N is the length of the array, and an is the internal element type of the array [] array name = new type [n]; // allocates memory for the array, however, no initial value is assigned (vs automatically assigns it an initial value of 0) type [] array name = new type [n] {a1, a2 ,..., An} // initialize and assign the initial value type [] array name = new type [] {a1, a2 ,..., An} // you can also choose not to specify the array length. The compiler will automatically count the number of elements type [] array name = {a1, a2 ,..., An} // C-style initialization and assignment
When accessing the array, access the I-1 elements in the way of array name [I. If you do not know the Length of the array, you can use the Length attribute.
Note: If the element type in the array is a reference type, you must allocate memory for each element. In C #, "type []" is an integral whole, and "Type []" can be considered as an array type.
<2> multidimensional array
After reading the one-dimensional array, we now promote the multi-dimensional array and declare the Syntax:
Type [,] array name; // two-dimensional array type [,] array name; // three-dimensional array
I believe you have also discovered that the number of commas + 1 in square brackets is the dimension of the array. Let's take a two-dimensional array as an example to look at the multi-dimensional array initialization:
int[,] arr = new int[2,3]{{1,2,3},{4,5,6}};
The difference between multi-dimensional array initialization and one-dimensional array Initialization is that each dimension must be enclosed by braces during multi-dimensional array initialization. The rest are the same as the one-dimensional array initialization method.
<3> jagged array
In the process of using multi-dimensional arrays, we sometimes do not need to have the same dimension, so we introduce a sawtooth array. (The Vector in C ++ also has a similar function ). The preceding figure shows the differences between a two-dimensional array and a sawtooth array:
Now let's look at his declaration Syntax:
Type [] [] array name = new type [n] []; // n is the dimension of the Sawtooth array, and the last square brackets are empty
Let's use a specific instance to see how it works:
Int [] [] Testarray = new int [2] []; Testarray [0] = new int [3] {1, 2, 3}; // Of course, you can also leave the initial value unspecified, we recommend that you first assign the initial value Testarray [1] = new int [4] {1, 2, 4 };
At this time, some people may wonder how to traverse the entire array simply because the length of each dimension is different? In this case, the Length attribute can take advantage of it. Let's take the preceding example:
for(int i = 0; i < Testarray.Length; i++){for(int j = 0; j < Testarray[i].Length; j++){//TODO:}}
<4> array as a parameter
Since we regard the array as a type, it can also be passed to the method as a parameter or returned from the method. C # arrays support covariant, but array covariant can only be usedReference Type, Cannot be used for value type.
<5> array segment ArraySegment <T>
ArraySegment <T> can establish a ing between the array and operate on a specific segment of the array. The result of the operation is directly reflected in the array, otherwise, changes in the array are also reflected in the array segment. Let's take a look at the specific use:
ArraySegment<int> Test = new ArraySegment<int>(arr, 1, 4);
The preceding example indicates Test. four elements are referenced from arr [1. Test. Offset indicates the first referenced element, that is, arr [1].
2. Array class
We used square brackets to declare the Array. In fact, we implicitly used the Array class. From another perspective, we can regard all of them as subclasses derived from Array, for example, int [] and double, in this way, we can use Array to define methods and attributes for arrays.
<1> Create an array
Array is an abstract class, so it cannot be instantiated. However, you can use the static CreateInstance () method to create an array. Because CreateInstance () has multiple overloaded versions, let's take one of them as an example:
// Create an Array of the int type with a length of 5, TestArray Test = Array. createInstance (typeof (int), 5); // assign the value of Test [3] To 5Test. setValue (5, 3); // we want to return the value Test [3. getValue (3); // convert it to the int [] array int [] T1 = (int []) Test;
<2> copy an array
We can use the Clone () method to copy the array, but if the array is of reference type, we can only copy the references of the other side. If the array is of the value type, the other side can be completely copied. We can also use the Copy () method to create a superficial Copy.
Note: The biggest difference between Clone () and Copy (): The Copy () method must use the same order as the original array and have enough element space, but Cone () method will create an array larger than the original array.
<3> sort
The Array class also provides the QuickSort sorting algorithm. You can use the Sort () method to Sort arrays. However, to use the Sort () method, you need to implement the IComparable interface (. Net has implemented the IComparable interface for the basic data type, from small to large by default ). For a custom type, we must implement the IComparable <T> interface, which uses only one method CompareTo (). If the two are equal, 0 is returned. If the instance is before the parameter object, a value smaller than 0 is returned. Otherwise, a value greater than 0 is returned.
We can also implement the IComparer <T> and IComparer interfaces. Let's take a look at the differences between this interface and the IComparable interface:
① IComparable is implemented in the class of the object to be compared. You can compare this object with another object.
② IComparer must be implemented in a separate class and can compare any two objects.
3. Enumeration
You can use enumeration in the foreach statement to iterate the elements in the set without knowing the number of elements in the set. The foreach statement uses an enumerator. You can use foreach to iterate the set by implementing the IEnumerable interface. (The IEnumerable interface has been implemented by default for arrays and collections ).
<1> foreach principle and IEnumerator Interface
Foreach uses the methods and attributes of the IEnumerator interface.
// Per is the object of the Person class foreach (var p in per) {consystemic. WriteLine (p );}
C # the compiler will parse this code
IEnumerator<Person> em = per.GetEnumerator();while(em.MoveNext()){Person p = em.Current;Console.WriteLine(p);}
The MoveNext () method of the IEnumerator interface is used to move to the next element of the set. If yes, true is returned. Otherwise, false is returned. The Current attribute is the Current value.
<2> yield statement
As it is too cumbersome to create an enumerator, we introduced the yield statement to help us reduce the workload. yield return returns an element of the Set, and yield break can stop iteration.
The following is a simple example of yield usage:
public class TFoo{public IEnumerator<string> GetEnumerator(){yield return “Hello”;yield return “World”;}}
Now we use foreach to iterate the set
Int cnt = 0; // Let's use this to see how many times the set has iterated in foreach var Test = new TFoo (); foreach (var s in Test) {cnt ++; console. writeLine (s );}
Finally, we can get cnt = 2 and output Hello World. Through this instance, we can get a general idea of how yield works. We used yield in the linked list before learning generics.
Note: yield cannot appear in anonymous methods.
4. Tuple)
An array is used to process a large amount of data of the same type. How can we process different types of data in a similar way? Of course, we have introduced the Tuple class .. Net defines eight generic Tuple classes and a static Tuple. For example, Tuple <T1> contains an element of Type T1, Tuple <T1, T2> contains elements of Type T1 and T2, and so on.
If there are more than 8 tuples, 8th can be defined using the Tuple class. For example:
Tuple <T1, T2, T3, T4, T5, T6, T7, TRest> // TRest is another tuples.
We can use this method to create any number of tuples.
We use the Create () method to Create tuples, for example:
var Test = Tuple.Create<int,int>(2,5);
5. Structure comparison
Both arrays and element groups implement the IStructuralEquatable and IStructuralComparable interfaces. These two interfaces can not only be usedComparison reference, You can alsoComparison content. Because these interfaces are display implementations, You Need To forcibly convert arrays and element groups into this interface during use.
The IStructuralEquatable interface is used to compare whether two arrays or tuples have the same content.
The IStructuralComparable interface is used to sort arrays or tuples.
We use an instance to briefly understand the usage of the IStructuralEquatable interface:
public class Test{ public int Id { get; set; } public override bool Equals(object obj) { if (obj == null) return base.Equals(obj); else return this.Id == (obj as Test).Id; }}
Now let's define two class objects t1 and t2 with the same class content.
var t1 = new Test[2]{new Test{Id = 2}, new Test{Id = 3}};var t2 = new Test[2]{new Test{Id = 2}, new Test{Id = 3}};
If we use "=" or "! = "Then the compiler will only compare our references. Here we need to use the IStructuralEquatable interface.
(t1 as IStructuralEquatable).Equals(t2, EqualityComparer<Test>.Default)
In this case, we compare the content of t1 and t2. Because the content is compared, they will return True. EqualityComparer <Test>. the Default method calls the Test Default Equals () method. Therefore, we only need to override the Default Equals () method and compare the rules of the rewritten Equals () method class content, then we can compare whether the class objects have the same content.
For tuples e1 and e2, we can directly use e1.Equals (e2) to compare the content between tuples. However, if we use the comparison operators "=" and "! = "We can only compare their references.
(If any error occurs, please correct it. For more information, see the source)