Przeglądaj źródła

委托、接口、列表

master
QYYEE 5 lat temu
rodzic
commit
4ab5a5742f

+ 185
- 0
实践/后端/C#基础/24.委托.md Wyświetl plik

@@ -0,0 +1,185 @@
1
+> 委托
2
+- 当要把方法传递给其他方法时,就需要使用委托。
3
+  
4
+
5
+> 声明委托
6
+- 使用委托时
7
+    - 首先必须定义要使用的委托,对于委托,定义它就是告诉编译器这种类型的委托表示哪种类型的方法。
8
+    - 然后,必须创建该委托的一个或多个实例。编译器在后台将创建表示该委托的一个类。
9
+- 声明委托的语法如下:
10
+```
11
+delegate void IntMethodInvoker(int x);
12
+声明了一个委托IntMethodInvoker,并指定该委托的每个实例都可以包含一个方法的引用,该方法带有一个int参数,并返回void。
13
+委托的类型安全性非常高。在定义委托时,必须给出它所表示的方法的签名和返回类型等全部细节。
14
+```
15
+- 理解委托的一种好方式是把委托视为给方法的签名和返回类型指定名称。
16
+
17
+ 
18
+```
19
+定义一个委托TwoLongsOp,该委托表示的方法有两个long型参数,返回类型为double。
20
+delegate double TwoLongsOp(long first,long second);
21
+或者定义一个委托,它表示的方法不带参数,返回一个string型的值
22
+delegate string GetAStringent();
23
+```
24
+- 实际上,“定义一个委托”是指“定义一个新类”,委托实现为派生自基类System.MulticastDelegate的类,System.MulticastDelegate又派生自基类System.Delegate。
25
+
26
+> 使用委托
27
+- 在int值上调用ToString()方法的一种相当复杂的方式
28
+```
29
+private delegate string GetAString();
30
+public static void Main()
31
+{
32
+    int x=40;
33
+    GetAString firstStringMethod=newGetAString(x.ToString);
34
+    WriteLine($"String is (fistStringMethod{})");
35
+}
36
+```
37
+> 简单的委托示例
38
+- 定义一个类MathOperations,它有两个静态方法,对double类型的值执行两种操作。然后使用该委托调用这些方法。
39
+```
40
+class MathOperation
41
+{
42
+    public static double MultiplyByTwo(double value)=>value*2;
43
+    public static double Square(double value)=>value*value;
44
+}
45
+调用这些方法
46
+using static System.Console;
47
+namespace Wrox.ProCSharp.Delegates
48
+{
49
+    delegate double DoubleOp(double x);
50
+    class Program
51
+    {
52
+        static void Main()
53
+        {
54
+            DoubleOp[] operations=
55
+            {
56
+                MathOperation.MultiplyByTwo,
57
+                MathOperations.Square
58
+            };
59
+            for(int i=0;i<operations.Length;i++)
60
+            {
61
+                WriteLine($"Using operations[{i}]:");
62
+                ProcessAndDisplayNumber(operations[i],2.0);
63
+                ProcessAndDisplayNumber(operations[i],7.94);
64
+                ProcessAndDisplayNumber(operations[i],1.414);
65
+                WriteLine();
66
+            }
67
+        }
68
+        static void ProcessAndDisplayNumber(DoubleOp action,double value)
69
+        {
70
+            double result =action(value);
71
+            WriteLine($"Value is {value},result of operation is {result}");
72
+        }
73
+    }
74
+}
75
+```
76
+
77
+> Action<T>和Func<T>委托
78
+
79
+- 泛型Action<T>委托表示引用一个void返回类型的方法。这个委托类存在不同的变体,可以传递至多16种不同的参数类型。没有泛型参数的Action类可调用没有参数的方法。Action<in T>调用带一个参数的方法,Action<in T1,in T2>调用带两个参数的方法,Action<in T1,in T2,in T3,in T4,in T5,in T6,in T7,in T8>调用8个参数的方法。
80
+- Func<T>允许调用带返回类型的方法。与Action<T>类似,Func<T>也定义了不同的变体,至多也可以传递16个参数类型和一个返回类型。Func<out TResult>委托类型可以调用带返回类型且无参数的方法,Func<in T,out TResult>调用带一个参数的方法,func<in T1,in T2,in T3,in T4,out TResult>调用4个参数的方法。
81
+
82
+- delegate double DoubleOp(double x);
83
+- 除了声明自定义委托DoubleOp之外,还可以使用Func<int T,out TResult>委托。可以声明一个该委托类型的变量,或者声明该委托类型的数组
84
+```
85
+<double ,double>[] operations=
86
+{
87
+    MathOperations.MultiplyByTwo,
88
+    MathOperations.Square
89
+};
90
+使用委托,并将ProcessAndDisplayNumber()方法作为参数:
91
+static void ProcessAndDisplayNumber(Func<double,double>action,double value)
92
+{
93
+    double result=action(value);
94
+    WriteLine{$"Value is{value},result of operation is {result}"}
95
+}
96
+```
97
+**BubbleSorter示例**
98
+- 编写一个类BubbleSorter,它实现一个静态方法Sort(),这个方法的第一个参数是一个对象数组,把该数组按照升序重新排列。
99
+- 进行冒泡排序的方法如下:
100
+```
101
+bool swapped=true;
102
+do
103
+{
104
+    swapped=false;
105
+    for(int i=0;i<sortArray.Length-1;i++)
106
+    {
107
+        if(sortArray[i]>sortArray[i+1])
108
+        {
109
+            int temp=sortArray[i];
110
+            sortArray[i]=sortArray[i+1];
111
+            sortArry[i+1]=temp;
112
+            swapped=true;
113
+        }
114
+    }
115
+
116
+    
117
+}while(swapped);
118
+```
119
+- 定义BubbleSorter类
120
+```
121
+class BubbleSorter
122
+{
123
+    static public void Sort<T>(IList<T> sortArray,Func<T,T,bool>comparison)
124
+    {
125
+        bool swapped=true;
126
+        do
127
+        {
128
+            swapped=false;
129
+            for (int i=0;i<sortArray.Count-1;i++)
130
+            {
131
+                if(comparison(sortArray[i+1],sortArry[i]))
132
+                {
133
+                    T temp=sortArray[i];
134
+                    sortArray[i]=sortArray[i+1];
135
+                    sortArray[i+1]=temp;
136
+                    swapped=true;
137
+                }
138
+            } 
139
+        }while(swapped);
140
+    }
141
+}
142
+```
143
+- 为了使用这个类,需要定义另一个类,从而建立要排序的数组。假定Mortimer Phones移动电话公司有一个员工列表,要根据他们的薪水进行排序。每个员工分别由类Employee的一个实例表示,
144
+```
145
+class Employee
146
+{
147
+    public Employee(string name,decimal salary)
148
+    {
149
+        Name=name;
150
+        Salary=salary;
151
+    }
152
+    public string Name{get;}
153
+    public decimal Salary{get;private set;}
154
+    public override string ToString()=>$"{Name},{Salary:C}";
155
+    public static bool CompareSalary(Employee e1,Employee e2)=>e1.Salary<e2.Salary;
156
+}
157
+```
158
+- 为了匹配Func<T,T,bool>委托的签名,在这个类中必须定义CompareSalay,它的参数是两个Employee引用,并返回一个布尔值。
159
+```
160
+using static System.Console;
161
+
162
+namespace Wrox.ProCSharp.Delegates
163
+{
164
+    class Program
165
+    {
166
+        static void Main()
167
+        {
168
+            Employee[] employees=
169
+            {
170
+                new Employee("Bugs Bunny",20000),
171
+                new Employee("Elmer Fudd",10000),
172
+                new Employee("Daffy Duck",25000),
173
+                new Employee("Wile Coyote",1000000.38m),
174
+                new Employee("Foghorn Leghorn",23000),
175
+                new Employee("RoadRunner",50000)
176
+            };
177
+            BubbleSorter.Sort(employee,Employee.CompareSalary);
178
+            foreach(var employee in employees)
179
+            {
180
+                WriteLine(employee);
181
+            }
182
+        }
183
+    }
184
+}
185
+```

+ 115
- 0
实践/后端/C#基础/25.接口、列表.md Wyświetl plik

@@ -0,0 +1,115 @@
1
+>集合接口和类型
2
+- 大多数接口都可在System.Collections和System.Collections.Generic名称空间中找到。泛型集合类位于System.Collections.Generic名称空间中;
3
+  
4
+**接口及说明**
5
+- IEnumerable<T>:如果将foreach语句用于集合,就需要IEnumerable接口,这个接口定义了方法GetEnumerator(),它返回一个实现了IEnumerator接口的枚举。
6
+- ICollection<T>:ICollection<T>接口由泛型集合实现。使用这个接口可以获得集合中的元素个数,把集合复制到数组中(CopyTo()方法),还可以从集合中添加和删除元素(Add()、Remove()、Clear())
7
+- IList<T>:用于可通过位置访问其中的元素列表,这个接口定义了一个索引器,可以在集合的指定位置插入或删除某些项(Insert()和RemoveAt()方法).IList<T>接口派生自ICollection<T>接口
8
+- ISet<T>:该接口由集实现。集允许合并不同的集,获得两个集的交集,检查两个集是否重叠。ISet<T>接口派生自ICollection<T>接口
9
+- IDictionary<TKey,TValue>:由包含键和值得泛型集合类实现。使用这个接口可以访问所有的键和值,使用键类型的索引器可以访问某些项,还可以添加或删除某些项
10
+- ILookup<TKey,TValue>:类似于IDictionary<TKey,TValue>接口,实现该接口的集合有键和值,且可以通过一个键包含多个值
11
+- IComparer<T>:由比较器实现,通过Comparer()方法给集合中的元素排序
12
+- IEqualityComparer<T>:由一个比较器实现,该比较器可用于字典中的键,使用这个接口,可以对对象进行相等性比较
13
+
14
+
15
+> 列表
16
+
17
+- 例子:将Racer类中的成员用作要添加到集合中的元素,以表示一级方程式的一位赛车手。这个类有5个属性:Id、Firstname、Lastname、Country和Wins的次数。在该类的构造函数中,可以传递赛车手的姓名和获胜次数,以设置成员。重写ToString()是为了返回赛车手的姓名。Racer类也实现了泛型接口IComparable<T>,为Racer类中的元素排序,还实现了IFormattable接口
18
+```
19
+public class Racer:IComparable<Racer>,IFormattable
20
+{
21
+    public int Id{get;}
22
+    public string FirstName{get;set;}
23
+    public string LastName{get;set;}
24
+    public string Country{get;set;}
25
+    public int Wins{get;set;}
26
+
27
+    public Racer(int id,string firstName,string lastName,string country):this(id,firstName,lastName,country,wens:0)
28
+    {}
29
+    public Racer(int id,string firstName,string lastName,string country,int wins)
30
+    {
31
+        Id=id;
32
+        FirstName=firstName;
33
+        LastName=lastName;
34
+        Country=country;
35
+        Wins=wins;
36
+    }
37
+    public override string ToString()=>$"{FirstName}{LastName}";
38
+    public string ToString(string format,IFormatProvider formatProvider)
39
+    {
40
+        if(format==null)format="N";
41
+        switch {format.ToUpper()}
42
+        {
43
+            case "N":
44
+            return ToString();
45
+            case "F":
46
+            return FirstName;
47
+            case "L"
48
+            return LastName;
49
+            case "W"
50
+            return $"{ToString()},Wins:{Wins}";
51
+            case "C":
52
+            return $"{ToString()},Country:{Country}",
53
+            case "A"
54
+            return $"{ToString()},Country:{Country} Wins:{Wins}";
55
+            default:
56
+            throw new FormatException(String.Format(formatProvider,$"Format(format)is not supported"));
57
+        }
58
+    }
59
+    public string ToString(string format)=>ToString(format,null);
60
+    public int CompareTo(Racer other)
61
+    {
62
+        int compare=LastName?.CompareTo(other?.LastName)??-1;
63
+        if(compare==0)
64
+        {
65
+            return FirstName?.CompareTo(other?.FirstName)??-1;
66
+        }
67
+        return compare;
68
+    }
69
+}
70
+```
71
+
72
+> 创建列表
73
+- 集合初始值设定项
74
+```
75
+var intList=new List<int>(){1,2};
76
+var stringList=new List<string>(){"one","two"};
77
+```
78
+- 添加元素
79
+  - 使用Add()方法可以给列表添加元素
80
+  ```
81
+  var intList=new List<int>();
82
+  intList.Add(1);
83
+  intList.Add(2);
84
+
85
+  var stringList=new List<string>();
86
+  stringList.Add("one");
87
+  stringList.Add("two");
88
+  ```
89
+- 插入元素
90
+```
91
+racers.Insert(3,new Racer(6,"Phil","Hill","USA",3));
92
+方法InsertRange()提供了插入大量元素的功能,类似于前面的AddRanger()方法。
93
+```
94
+
95
+- 访问元素
96
+   - 实现了IList和IList<T>接口的所有类都提供了一个索引器,所以可以使用索引器,通过传递元素号来访问元素。
97
+   - 可以使用Count属性确定元素个数,再使用for循环遍历集合中的每个元素,并使用索引器访问每一项:
98
+    ```
99
+    for (int i=0;i<racers.Count;i++>)
100
+    {
101
+        WriteLine(racers[i]);
102
+    }
103
+    ```
104
+   - 因为List<T>集合类实现了IEnumerable接口,所以也可以使用foreach语句遍历集合中的元素
105
+    ```
106
+    foreach(var r in racers)
107
+    {
108
+        WriteLine(r);
109
+    }
110
+    ```
111
+- 删除元素
112
+- 搜索
113
+
114
+
115
+

Ładowanie…
Anuluj
Zapisz