- 浏览: 280493 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
jasonking412:
鄙视抄袭,都TMD一样的。
Openfire red5.war下载已经配置 -
xhg19901120:
有没有下载地址啊
【转】Android 多级菜单 -
yxl2005play:
为什么是404?博主,求解
Openfire red5.war下载已经配置 -
tan2416:
回复看看。。。。。
实现在popwindow中展示listview列表 -
liufeng7600:
你好,求教: 我可不可以在pc上用web浏览器访问 Andr ...
android中实现JavaScript与Java之间实现互相调用
1. 委托Delegate
C#中的Delegate对应于C中的指针,但是又有所不同C中的指针既可以指向方法,又可以指向变量,并且可以进行类型转换,
C中的指针实际上就是内存地址变量,他是可以直接操作内存的,通过内存地址直接访问变量,直接调用方法。
而C#中的Delegate是强类型的,也就是说在声明委托时就已经指定了该变量只能指向具有特定参数,以及返回值的方法。
使用delegate就可以直接建立任何名称的委托类型,当进行系统编译时,系统就会自动生成此类型。您可以使用delegate void MyDelegate()
方式建立一个委托类,并使用ILDASM.exe观察其成员。由ILDASM.exe 中可以看到,它继承了System.MulticastDelegate类,
并自动生成BeginInvoke、EndInvoke、Invoke 等三个常用方法。
Invoke 方法是用于同步调用委托对象的对应方法,而BeginInvoke、EndInvoke是用于以异步方式调用对应方法的。
1
2
3
4
5
6
7
8
|
public
class
MyDelegate:MulticastDelegate
{
//同步调用委托方法
public
virtual
void
Invoke();
//异步调用委托方法
public
virtual
IAsyncResult BeginInvoke(AsyncCallback callback,
object
state);
public
virtual
void
EndInvoke(IAsyncResult result);
}
|
MulticastDelegate是System.Delegate的子类,它是一个特殊类,编译器和其他工具可以从此类派生,但是自定义类不能 显式地从此类进行派生。它支持多路广播委托,并拥有一个带有链接的委托列表,在调用多路广播委托时,系统将按照调用列表中的委托出现顺序来同步调用这些委 托。
MulticastDelegate具有两个常用属性:Method、Target。其中Method 用于获取委托所表示的方法Target 用于获取当前调用的类实例。
1.1 委托的使用
当建立委托对象时,委托的参数类型必须与委托方法相对应。只要向建立委托对象的构造函数中输入方法名称example.Method,委托就会直接 绑定此方法。使用myDelegate.Invoke(string message),就能显式调用委托方法。但在实际的操作中,我们无须用到 Invoke 方法,而只要直接使用myDelegate(string message),就能调用委托方法。
无返回值的委托
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class
Program
{
delegate
void
MyDelegate(
string
message);
public
class
Example
{
public
void
Method(
string
message)
{
MessageBox.Show(message);
}
}
static
void
Main(
string
[] args)
{
Example example=
new
Example();
MyDelegate myDelegate=
new
MyDelegate(example.Method);
myDelegate(
"Hello World"
);
Console.ReadKey();
}
}
|
有返回值的委托
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class
Program
{
delegate
string
MyDelegate(
string
message);
public
class
Example
{
public
string
Method(
string
name)
{
return
"Hello "
+ name;
}
}
static
void
Main(
string
[] args)
{
Example example=
new
Example();
//绑定委托方法
MyDelegate myDelegate=
new
MyDelegate(example.Method);
//调用委托,获取返回值
string
message = myDelegate(
"Leslie"
);
Console.WriteLine(message);
Console.ReadKey();
}
}
|
多路广播委托
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
delegate
double
MyDelegate(
double
message);
public
class
Price
{
public
double
Ordinary(
double
price)
{
double
price1 = 0.95 * price;
Console.WriteLine(
"Ordinary Price : "
+price1);
return
price1;
}
public
double
Favourable(
double
price)
{
double
price1 = 0.85 * price;
Console.WriteLine(
"Favourable Price : "
+ price1);
return
price1;
}
static
void
Main(
string
[] args)
{
Price price =
new
Price();
//绑定Ordinary方法
MyDelegate myDelegate =
new
MyDelegate(price.Ordinary);
//绑定Favourable方法
myDelegate +=
new
MyDelegate(price.Favourable);
//调用委托
Console.WriteLine(
"Current Price : "
+ myDelegate(100));
Console.ReadKey();
}
}
|
输出
1.2 委托的协变与逆变
前面已经说过,委托是强类型的方法指针,但是在面对具有继承关系类型的参数、或者返回值时,委托是如何处理的呢。
协变(返回值类型具有继承关系的方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
class
Worker
{.......}
public
class
Manager:Worker
{.......}
class
Program
{
public
delegate
Worker GetWorkerHandler(
int
id);
//在 Framework2.0 以上,委托 GetWorkerHandler 可绑定 GetWorker 与 GetManager 两个方法
public
static
Worker GetWorker(
int
id)
{
Worker worker =
new
Worker();
return
worker;
}
public
static
Manager GetManager(
int
id)
{
Manager manager =
new
Manager();
return
manager;
}
static
void
Main(
string
[] args)
{
GetWorkerHandler workerHandler =
new
GetWorkerHandler(GetWorker);
Worker worker=workerHandler(1);
GetWorkerHandler managerHandler =
new
GetWorkerHandler(GetManager);
Manager manager = managerHandler(2)
as
Manager;
Console.ReadKey();
}
}
|
委托 GetWorkerHandler 可以绑定 GetWorker 与 GetManager 两个方法
逆变
委托逆变,是指委托方法的参数同样可以接收 “继承” 这个传统规则。像下面的例子,以 object 为参数的委托,可以接受任何 object 子类的对象作为参数。最后可以在处理方法中使用 is 对输入数据的类型进行判断,分别处理对不同的类型的对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class
Program
{
public
delegate
void
Handler(
object
obj);
public
static
void
GetMessage(
object
message)
{
if
(message
is
string
)
Console.WriteLine(
"His name is : "
+ message.ToString());
if
(message
is
int
)
Console.WriteLine(
"His age is : "
+ message.ToString());
}
static
void
Main(
string
[] args)
{
Handler handler =
new
Handler(GetMessage);
handler(29);
Console.ReadKey();
}
}
|
注意 : 委托与其绑定方法的参数必须一至,即当 Handler 所输入的参数为 object 类型,其绑定方法 GetMessage 的参数也必须为 object 。否则,即使绑定方法的参数为 object 的子类,系统也无法辨认。
大家可能注意到了,这个委托方法GetMessage的实现不是那么优雅,于是泛型委托应运而生。
class Program { public delegate void Handler<T>(T obj); public static void GetWorkerWages(Worker worker) { Console.WriteLine("Worker's total wages is " + worker.Wages); } public static void GetManagerWages(Manager manager) { Console.WriteLine("Manager's total wages is "+manager.Wages); } static void Main(string[] args) { Handler<Worker> workerHander = new Handler<Worker>(GetWorkerWages); Worker worker = new Worker(); worker.Wages = 3000; workerHander(worker); Handler<Manager> managerHandler = new Handler<Manager>(GetManagerWages); Manager manager = new Manager(); manager.Wages = 4500; managerHandler(manager); Console.ReadKey(); } }
2. event事件的由来
事件是特殊的委托,他为委托提供了封装性,一方面允许从类的外部增加,删除绑定方法,另一方面又不允许从类的外部来触发委托所绑定了方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
public
delegate
double
PriceHandler();
public
class
PriceManager
{
public
PriceHandler GetPriceHandler;
//委托处理,当价格高于100元按8.8折计算,其他按原价计算
public
double
GetPrice()
{
if
(GetPriceHandler.GetInvocationList().Count() > 0)
{
if
(GetPriceHandler() > 100)
return
GetPriceHandler()*0.88;
else
return
GetPriceHandler();
}
return
-1;
}
}
class
Program
{
static
void
Main(
string
[] args)
{
PriceManager priceManager =
new
PriceManager();
//调用priceManager的GetPrice方法获取价格
//直接调用委托的Invoke获取价格,两者进行比较
priceManager.GetPriceHandler =
new
PriceHandler(ComputerPrice);
Console.WriteLine(
string
.Format(
"GetPrice\n Computer's price is {0}!"
,
priceManager.GetPrice()));
Console.WriteLine(
string
.Format(
"Invoke\n Computer's price is {0}!"
,
priceManager.GetPriceHandler.Invoke()));
Console.WriteLine();
priceManager.GetPriceHandler =
new
PriceHandler(BookPrice);
Console.WriteLine(
string
.Format(
"GetPrice\n Book's price is {0}!"
,
priceManager.GetPrice()));
Console.WriteLine(
string
.Format(
"Invoke\n Book's price is {0}!"
,
priceManager.GetPriceHandler.Invoke()));
Console.ReadKey();
}
//书本价格为98元
public
static
double
BookPrice()
{
return
98.0;
}
//计算机价格为8800元
public
static
double
ComputerPrice()
{
return
8800.0;
}
}
|
以上代码实现了对于100元以上商品的的88折处理。一方面为了给GetPriceHandler 绑定方法就必须将委托声明为public,但是一旦声明为public
就可以在类外部直接通过Invoke来调用该委托所绑定的方法,而产生我们不需要的结果。
当然我们可以将GetPriceHandler 声明为private并且通过public 的addHandler,removeHandler来消除委托public的副作用,但是C#提供了更加优雅的方法:
那就是event关键字。
事件(event)可被视作为一种特别的委托,它为委托对象隐式地建立起add_XXX、remove_XXX 两个方法,用作注册与注销事件的处理方法。而且事件对应的变量成员将会被视为 private 变量,外界无法超越事件所在对象直接访问它们,这使事件具备良好的封装性,而且免除了add_XXX、remove_XXX等繁琐的代码。
1
2
3
4
5
|
public
class
EventTest
{
public
delegate
void
MyDelegate();
public
event
MyDelegate MyEvent;
}
|
观察事件的编译过程可知,在编译的时候,系统为 MyEvent 事件自动建立add_MyEvent、remove_MyEvent 方法。
事件能通过+=和-=两个方式注册或者注销对其处理的方法,使用+=与-=操作符的时候,系统会自动调用对应的 add_XXX、remove_XXX 进行处理。
值
得留意,在PersonManager类的Execute方法中,如果 MyEvent
绑定的处理方法不为空,即可使用MyEvent(string)引发事件。但如果在外界的 main 方法中直接使用
personManager.MyEvent (string)
来引发事件,系统将引发错误报告。这正是因为事件具备了良好的封装性,使外界不能超越事件所在的对象访问其变量成员。
注意 :在事件所处的对象之外,事件只能出现在+=,-=的左方。
public delegate void MyDelegate(string name);
public class PersonManager
{
public event MyDelegate MyEvent;
//执行事件
public void Execute(string name)
{
if (MyEvent != null)
MyEvent(name);
}
}
class Program
{
static void Main(string[] args)
{
PersonManager personManager = new PersonManager();
//绑定事件处理方法
personManager.MyEvent += new MyDelegate(GetName);
personManager.Execute("Leslie");
Console.ReadKey();
}
public static void GetName(string name)
{
Console.WriteLine("My name is " + name);
}
}
在绑定事件处理方法的时候,事件出现在+=、-= 操作符的左边,对应的委托对象出现在+=、-= 操作符的右边。对应以上例子,事件提供了更简单的绑定方式,只需要在+=、-= 操作符的右方写上方法名称,系统就能自动辩认。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public
delegate
void
MyDelegate(
string
name);
public
class
PersonManager
{
public
event
MyDelegate MyEvent;
.........
}
class
Program
{
static
void
Main(
string
[] args)
{
PersonManager personManager =
new
PersonManager();
//绑定事件处理方法
personManager.MyEvent += GetName;
.............
}
public
static
void
GetName(
string
name)
{.........}
}
|
如果觉得编写 GetName 方法过于麻烦,你还可以使用匿名方法绑定事件的处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public
delegate
void
MyDelegate(
string
name);
public
class
PersonManager
{
public
event
MyDelegate MyEvent;
//执行事件
public
void
Execute(
string
name)
{
if
(MyEvent !=
null
)
MyEvent(name);
}
static
void
Main(
string
[] args)
{
PersonManager personManager =
new
PersonManager();
//使用匿名方法绑定事件的处理
personManager.MyEvent +=
delegate
(
string
name){
Console.WriteLine(
"My name is "
+name);
};
personManager.Execute(
"Leslie"
);
Console.ReadKey();
}
}
|
1
|
|
3. lambda表达式
在Framework 2.0 以前,声明委托的唯一方法是通过方法命名,从Framework 2.0 起,系统开始支持匿名方法。
通过匿名方法,可以直接把一段代码绑定给事件,因此减少了实例化委托所需的编码系统开销。
而在 Framework 3.0 开始,Lambda 表达式开始逐渐取代了匿名方法,作为编写内联代码的首选方式。总体来说,Lambda 表达式的作用是为了使用更简单的方式来编写匿名方法,彻底简化委托的使用方式。
使用匿名方法
1
2
3
4
5
6
7
|
static
void
Main(
string
[] args)
{
Button btn =
new
Button();
btn.Click+=
delegate
(
object
obj,EventArgs e){
MessageBox.Show(
"Hello World !"
);
};
}
|
使用lambda表达式
1
2
3
4
5
6
7
|
static
void
Main(
string
[] args)
{
Button btn =
new
Button();
btn.Click+=(
object
obj,EventArgs e)=>{
MessageBox.Show(
"Hello World !"
);
};
}
|
3.1常用泛型委托
public delegate bool Predicate<T>(T obj)
它是一个返回bool的泛型委托,能接受一个任意类型的对象作为参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
class
Program
{
static
void
Main(
string
[] args)
{
List<Person> list = GetList();
//绑定查询条件
Predicate<Person> predicate =
new
Predicate<Person>(Match);
List<Person> result = list.FindAll(predicate);
Console.WriteLine(“Person count
is
: ” + result.Count);
Console.ReadKey();
}
//模拟源数据
static
List<Person> GetList()
{
var personList =
new
List<Person>();
var person1 =
new
Person(1,
"Leslie"
,29);
personList.Add(person1);
........
return
personList;
}
//查询条件
static
bool
Match(Person person)
{
return
person.Age <= 30;
}
}
public
class
Person
{
public
Person(
int
id,
string
name,
int
age)
{
ID = id;
Name = name;
Age = age;
}
public
int
ID
{
get
;
set
; }
public
string
Name
{
get
;
set
; }
public
int
Age
{
get
;
set
; }
}
|
1
|
|
Action<T> 的使用方式与 Predicate<T> 相似,不同之处在于 Predicate<T> 返回值为 bool , Action<T> 的返回值为 void。
Action 支持0~16个参数,可以按需求任意使用。
public delegate void Action()
public delegate void Action<T1>(T1 obj1)
public delegate void Action<T1,T2> (T1 obj1, T2 obj2)
public delegate void Action<T1,T2,T3> (T1 obj1, T2 obj2,T3 obj3)
............
public delegate void Action<T1,T2,T3,......,T16> (T1 obj1, T2 obj2,T3 obj3,......,T16 obj16)
1
2
3
4
5
6
7
8
9
10
11
|
static
void
Main(
string
[] args)
{
Action<
string
> action=ShowMessage;
action(
"Hello World"
);
Console.ReadKey();
}
static
void
ShowMessage(
string
message)
{
MessageBox.Show(message);
}
|
1
|
|
委托 Func 与 Action 相似,同样支持 0~16 个参数,不同之处在于Func 必须具有返回值
public delegate TResult Func<TResult>()
public delegate TResult Func<T1,TResult>(T1 obj1)
public delegate TResult Func<T1,T2,TResult>(T1 obj1,T2 obj2)
public delegate TResult Func<T1,T2,T3,TResult>(T1 obj1,T2 obj2,T3 obj3)
............
public delegate TResult Func<T1,T2,T3,......,T16,TResult>(T1 obj1,T2 obj2,T3 obj3,......,T16 obj16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
static
void
Main(
string
[] args)
{
Func<
double
,
bool
,
double
> func = Account;
double
result=func(1000,
true
);
Console.WriteLine(
"Result is : "
+result);
Console.ReadKey();
}
static
double
Account(
double
a,
bool
condition)
{
if
(condition)
return
a * 1.5;
else
return
a * 2;
}
|
3.2 lambda表达式
Lambda 的表达式的编写格式如下:
x=> x * 1.5
当中 “ => ” 是 Lambda 表达式的操作符,在左边用作定义一个参数列表,右边可以操作这些参数。
例子一, 先把 int x 设置 1000,通过 Action 把表达式定义为 x=x+500 ,最后通过 Invoke 激发委托。
static void Main(string[] args)
{
int x = 1000;
Action action = () => x = x + 500;
action.Invoke();
Console.WriteLine("Result is : " + x);
Console.ReadKey();
}
例子二,通过 Action<int> 把表达式定义 x=x+500, 到最后输入参数1000,得到的结果与例子一相同。
注意,此处Lambda表达式定义的操作使用 { } 括弧包括在一起,里面可以包含一系列的操作。
static void Main(string[] args)
{
Action<int> action = (x) =>
{
x = x + 500;
Console.WriteLine("Result is : " + x);
};
action.Invoke(1000);
Console.ReadKey();
}
相关推荐
C# Lamda表达式简单运用
委托、匿名方法和Lambda表达式是C#编程语言中的核心概念,它们在处理函数式编程和事件处理等方面发挥着重要作用。下面将详细解释这三个概念及其相互关系。 **委托(Delegate)** 委托在C#中是一种类型,它代表了一...
在.NET框架中,尤其是C#语言,Lambda表达式被广泛应用于LINQ(Language Integrated Query)查询中。 #### Lambda表达式的基本语法 Lambda表达式的一般形式如下: ```csharp (parameters) => expression ``` 或者 `...
本课程主要针对于Java 8(JDK 1.8)的新特性Lamda表达式进行了全面讲解。讲解了java基于函数编程的语法,以及与Lamda表达式操作有关的内建接口、批处理、MapReduce数据分析汇总处理。
在.NET框架中,C#是一种强大的编程语言,它支持Lambda表达式,这使得代码更加简洁、易读。Lambda表达式通常用于LINQ(Language Integrated Query)查询,它允许程序员使用类似SQL的语法在内存中的数据集上进行操作。...
在本压缩包文件"lamda表达式.rar"中,可能包含有关如何理解和使用C# Lambda表达式的详细教程或示例代码。 Lambda表达式的基本语法如下: ```csharp 参数 => 表达式 或 (参数列表) => { 代码块 } ``` 1. **单行...
在C#中,Lambda表达式可以与委托类型结合使用,如`Func`和`Action`。`Func`用于表示有返回值的函数,而`Action`用于表示无返回值的函数。例如,`Func, int, int>`表示接受两个整数并返回一个整数的委托类型,这与...
### Lambda 表达式及其在 C# 中的应用 在 C# 的高级编程中,Lambda 表达式的理解和应用是至关重要的。随着 C# 4.0 的推出,一系列新的编程特性如 LINQ 和 Lambda 表达式等为开发者提供了更多便利和强大的功能。本文...
### Java 8 Lambda 表达式之函数式接口详解 #### 一、引言 Java 8 的引入带来了一系列重大的变化,其中 Lambda 表达式作为最具革命性的特性之一,极大地简化了代码编写,提高了程序的可读性和可维护性。在前两篇...
jdk1.8的特性
随着技术的发展,开发者们探索出一种新的方式来实现路由功能——基于Lamda表达式的强类型Routing。 首先,传统的路由注册方式是通过在路由配置文件RouteConfig.cs中使用MapRoute方法来定义路由模板。然而,随着MVC ...
lamda出来很久了最近老师说用lamda表达式来做一个Button的按钮事件,初略的将自己的做法和感想分享给大家 先说 AS 如何支持 Lambda 表达式 1.首先确定你的AndroidStudio中使用的是大于jdk1.8的版本 2、在项目的根...
结合std::function和bind,lambda表达式可以方便地用于异步编程、事件处理、回调等场景。例如,你可以将lambda函数赋值给std::function,然后通过bind来固定参数,这样就可以创建出可定制的回调函数。 总结来说,...
在本文中,我们将深入探讨Qt库中的线程池(Thread Pool)机制,以及如何结合使用信号槽(Signals and Slots)和跨线程的lambda表达式。这些技术在多线程编程中扮演着至关重要的角色,特别是在GUI应用中,能够帮助...
Lambda表达式是Java 8引入的一种新特性,它极大地简化了函数式编程,使得代码更加简洁、优雅。...在日常开发中,我们应尽可能地利用Lambda表达式来优化代码,尤其是处理集合操作、多线程和事件驱动编程等场景。
### Java系列JDK 1.8 新特性之 Lambda表达式 #### 1、Lambda表达式介绍 Lambda表达式是Java 8中引入的一个重要新特性,它允许开发者以一种更加简洁的方式编写函数式接口实现代码。Lambda表达式本质上是一个匿名...
Lambda表达式是C++11新特性中的一种,全新的特性听起来很深奥,但却是很多其他语言早已提供(比如C#)或者即将提供(比如Java)的。Lambda表达式就是用于创建匿名函数的,GCC 4.5.x和Microsoft Visual Studio早已...