- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章结合.net框架在C#派生类中触发基类事件及实现接口事件由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
在派生类中引发基类事件 以下简单示例演示了在基类中声明可从派生类引发的事件的标准方法。此模式广泛应用于 .NET Framework 类库中的 Windows 窗体类。 在创建可用作其他类的基类的类时,应考虑如下事实:事件是特殊类型的委托,只可以从声明它们的类中调用。派生类无法直接调用基类中声明的事件。尽管有时需要事件仅由基类引发,但在大多数情形下,应该允许派生类调用基类事件。为此,您可以在包含该事件的基类中创建一个受保护的调用方法。通过调用或重写此调用方法,派生类便可以间接调用该事件。 注意:不要在基类中声明虚拟事件,也不要在派生类中重写这些事件。C# 编译器无法正确处理这些事件,并且无法预知的该派生的事件的用户是否真正订阅了基类事件.
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
namespace
BaseClassEvents
{
using
System;
using
System.Collections.Generic;
// Special EventArgs class to hold info about Shapes.
public
class
ShapeEventArgs : EventArgs
{
private
double
newArea;
public
ShapeEventArgs(
double
d)
{
newArea = d;
}
public
double
NewArea
{
get
{
return
newArea; }
}
}
// Base class event publisher
public
abstract
class
Shape
{
protected
double
area;
public
double
Area
{
get
{
return
area; }
set
{ area = value; }
}
// The event. Note that by using the generic EventHandler<T> event type
// we do not need to declare a separate delegate type.
public
event
EventHandler<ShapeEventArgs> ShapeChanged;
public
abstract
void
Draw();
//The event-invoking method that derived classes can override.
protected
virtual
void
OnShapeChanged(ShapeEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<ShapeEventArgs> handler = ShapeChanged;
if
(handler !=
null
)
{
handler(
this
, e);
}
}
}
public
class
Circle : Shape
{
private
double
radius;
public
Circle(
double
d)
{
radius = d;
area = 3.14 * radius * radius;
}
public
void
Update(
double
d)
{
radius = d;
area = 3.14 * radius * radius;
OnShapeChanged(
new
ShapeEventArgs(area));
}
protected
override
void
OnShapeChanged(ShapeEventArgs e)
{
// Do any circle-specific processing here.
// Call the base class event invocation method.
base
.OnShapeChanged(e);
}
public
override
void
Draw()
{
Console.WriteLine(
"Drawing a circle"
);
}
}
public
class
Rectangle : Shape
{
private
double
length;
private
double
width;
public
Rectangle(
double
length,
double
width)
{
this
.length = length;
this
.width = width;
area = length * width;
}
public
void
Update(
double
length,
double
width)
{
this
.length = length;
this
.width = width;
area = length * width;
OnShapeChanged(
new
ShapeEventArgs(area));
}
protected
override
void
OnShapeChanged(ShapeEventArgs e)
{
// Do any rectangle-specific processing here.
// Call the base class event invocation method.
base
.OnShapeChanged(e);
}
public
override
void
Draw()
{
Console.WriteLine(
"Drawing a rectangle"
);
}
}
// Represents the surface on which the shapes are drawn
// Subscribes to shape events so that it knows
// when to redraw a shape.
public
class
ShapeContainer
{
List<Shape> _list;
public
ShapeContainer()
{
_list =
new
List<Shape>();
}
public
void
AddShape(Shape s)
{
_list.Add(s);
// Subscribe to the base class event.
s.ShapeChanged += HandleShapeChanged;
}
// ...Other methods to draw, resize, etc.
private
void
HandleShapeChanged(
object
sender, ShapeEventArgs e)
{
Shape s = (Shape)sender;
// Diagnostic message for demonstration purposes.
Console.WriteLine(
"Received event. Shape area is now {0}"
, e.NewArea);
// Redraw the shape here.
s.Draw();
}
}
class
Test
{
static
void
Main(
string
[] args)
{
//Create the event publishers and subscriber
Circle c1 =
new
Circle(54);
Rectangle r1 =
new
Rectangle(12, 9);
ShapeContainer sc =
new
ShapeContainer();
// Add the shapes to the container.
sc.AddShape(c1);
sc.AddShape(r1);
// Cause some events to be raised.
c1.Update(57);
r1.Update(7, 7);
// Keep the console window open in debug mode.
System.Console.WriteLine(
"Press any key to exit."
);
System.Console.ReadKey();
}
}
}
|
输出:
1
2
3
4
|
Received event. Shape area is now 10201.86
Drawing a circle
Received event. Shape area is now 49
Drawing a rectangle
|
实现接口事件 。
接口可声明事件。下面的示例演示如何在类中实现接口事件。实现接口事件的规则与实现任何接口方法或属性的规则基本相同。 在类中实现接口事件 在类中声明事件,然后在适当的区域调用该事件.
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
|
namespace
ImplementInterfaceEvents
{
public
interface
IDrawingObject
{
event
EventHandler ShapeChanged;
}
public
class
MyEventArgs : EventArgs
{
// class members
}
public
class
Shape : IDrawingObject
{
public
event
EventHandler ShapeChanged;
void
ChangeShape()
{
// Do something here before the event…
OnShapeChanged(
new
MyEventArgs(
/*arguments*/
));
// or do something here after the event.
}
protected
virtual
void
OnShapeChanged(MyEventArgs e)
{
if
(ShapeChanged !=
null
)
{
ShapeChanged(
this
, e);
}
}
}
}
|
下面的示例演示如何处理以下的不常见情况:您的类是从两个以上的接口继承的,每个接口都含有同名事件)。在这种情况下,您至少要为其中一个事件提供显式接口实现。为事件编写显式接口实现时,必须编写 add 和 remove 事件访问器。这两个事件访问器通常由编译器提供,但在这种情况下编译器不能提供。 您可以提供自己的访问器,以便指定这两个事件是由您的类中的同一事件表示,还是由不同事件表示。例如,根据接口规范,如果事件应在不同时间引发,则可以将每个事件与类中的一个单独实现关联。在下面的示例中,订户将形状引用强制转换为 IShape 或 IDrawingObject,从而确定自己将会接收哪个 OnDraw 事件.
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
namespace
WrapTwoInterfaceEvents
{
using
System;
public
interface
IDrawingObject
{
// Raise this event before drawing
// the object.
event
EventHandler OnDraw;
}
public
interface
IShape
{
// Raise this event after drawing
// the shape.
event
EventHandler OnDraw;
}
// Base class event publisher inherits two
// interfaces, each with an OnDraw event
public
class
Shape : IDrawingObject, IShape
{
// Create an event for each interface event
event
EventHandler PreDrawEvent;
event
EventHandler PostDrawEvent;
object
objectLock =
new
Object();
// Explicit interface implementation required.
// Associate IDrawingObject's event with
// PreDrawEvent
event
EventHandler IDrawingObject.OnDraw
{
add
{
lock
(objectLock)
{
PreDrawEvent += value;
}
}
remove
{
lock
(objectLock)
{
PreDrawEvent -= value;
}
}
}
// Explicit interface implementation required.
// Associate IShape's event with
// PostDrawEvent
event
EventHandler IShape.OnDraw
{
add
{
lock
(objectLock)
{
PostDrawEvent += value;
}
}
remove
{
lock
(objectLock)
{
PostDrawEvent -= value;
}
}
}
// For the sake of simplicity this one method
// implements both interfaces.
public
void
Draw()
{
// Raise IDrawingObject's event before the object is drawn.
EventHandler handler = PreDrawEvent;
if
(handler !=
null
)
{
handler(
this
,
new
EventArgs());
}
Console.WriteLine(
"Drawing a shape."
);
// RaiseIShape's event after the object is drawn.
handler = PostDrawEvent;
if
(handler !=
null
)
{
handler(
this
,
new
EventArgs());
}
}
}
public
class
Subscriber1
{
// References the shape object as an IDrawingObject
public
Subscriber1(Shape shape)
{
IDrawingObject d = (IDrawingObject)shape;
d.OnDraw +=
new
EventHandler(d_OnDraw);
}
void
d_OnDraw(
object
sender, EventArgs e)
{
Console.WriteLine(
"Sub1 receives the IDrawingObject event."
);
}
}
// References the shape object as an IShape
public
class
Subscriber2
{
public
Subscriber2(Shape shape)
{
IShape d = (IShape)shape;
d.OnDraw +=
new
EventHandler(d_OnDraw);
}
void
d_OnDraw(
object
sender, EventArgs e)
{
Console.WriteLine(
"Sub2 receives the IShape event."
);
}
}
public
class
Program
{
static
void
Main(
string
[] args)
{
Shape shape =
new
Shape();
Subscriber1 sub =
new
Subscriber1(shape);
Subscriber2 sub2 =
new
Subscriber2(shape);
shape.Draw();
// Keep the console window open in debug mode.
System.Console.WriteLine(
"Press any key to exit."
);
System.Console.ReadKey();
}
}
}
|
输出:
1
2
3
|
Sub1 receives the IDrawingObject event.
Drawing a shape.
Sub2 receives the IShape event.
|
最后此篇关于结合.net框架在C#派生类中触发基类事件及实现接口事件的文章就讲到这里了,如果你想了解更多关于结合.net框架在C#派生类中触发基类事件及实现接口事件的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个无法理解的奇怪编译问题。 //I know, you should never derive from the STL Library template class SharedClass :
我是一个刚开始学习 Haskell 的菜鸟,所以如果我问愚蠢的问题,请耐心等待。 最近我在 SO 中遇到了演示如何导出函数和表达式的类型和实现的问题(诸如 How can I understand "
如何自动派生此 GADT 的 Read 实例: {-# LANGUAGE GADTs, StandaloneDeriving #-} data TypeDec a where TypeDecInt
我遇到了我想要的情况 Deal class要注意它DealDetail type反之亦然,我想 DealDetail注意Deal type .将来我想有很多 Deal 的后代和 DealDetails
我是 C# 新手,所以请多多包涵。 好的,所以我在不同的程序集中有两个类需要相互引用: namespace AssemblyA { class A { private B MyB {
简而言之,我已经实现了一个派生自 SynchronizationContext 的类,以便 GUI 应用程序可以轻松地使用在 GUI 线程以外的线程上引发的事件。我非常感谢对我的实现的评论。具体来说,
我正在设计一个小型系统,想知道如何为派生类分配内存的细微差别。 如果我有两个类(class) class foo { public: int a; Foo(): a(0) {}; }; class
我正在尝试编写一个派生 PartialEq 的枚举,其中包含一个手动执行此操作的特征对象。我使用了解决方案 here为了强制 Trait 的实现者编写相等方法。这无法编译: trait Trait {
以下代码可以编译(特别是 MyError 被识别为具有调试特性): use std::str; use std::fmt; #[derive(Debug)] enum MyError where F:
是否有一种简单的方法来注释结构中的字段,以便在派生 PartialEq 特征时忽略它们?例如: #[derive(PartialEq,Eq)] pub struct UndirectedGraph {
我正在编写代码来处理“Foo”类型的对象。 foo 是一种容器,为了提供对其元素的高效和抽象访问,它提供了 Element 类型的嵌套类。 Element 包装对象在容器中的位置。 现在,“Foo”可
假设如下: class child : public parent { public: fun1(parent * obj); //somewhere on the child class
我有几个模板类 template class Transition { public: virtual Cost getCost() = 0; }; template class St
我正在尝试使用自定义 QSortFilterProxyModel . 这是我的标题: #include class QSortFilterProxyModel_NumbersLast : publi
我正在使用 C# 和 mvc3。我在解决方案中添加了一个项目。我想创建一个新 Controller 并让它从我添加的项目中的 Controller 派生。我该怎么做? 最佳答案 在 Visual St
我在 python 中有一个对象,它派生自 QtGui.QGraphicsPixmapItem,具有一些基本属性和方法。在对此对象的引用上调用 deepcopy 后,当我尝试使用该副本时收到一条错误消
由于只能给FixedDocument添加页面,所以我写了一个派生类: public class CustomFixedDocument : FixedDocument { public voi
我在自定义 QMainWindow 时遇到了很大的问题,因为我不知道如何实现以下内容: 在 QMainWindow 文档中,QMainWindow 有一些用于工具栏、停靠小部件、状态栏和其他的特殊区域
我想感受一下QT,决定写一个小的十六进制编辑器。为此,我需要一个允许滚动的小部件。经过一番研究,我发现 QTextEdit 为此目的派生自 QAbstractScrollArea。在阅读 QAbstr
我正在寻找一种可以从已经发生的洗牌过程中派生出 key 的算法。 假设我们有被打乱的字符串“Hello”: "hello" -> "loelh" 现在我想从中导出一个 key k,我可以用它来撤销洗牌
我是一名优秀的程序员,十分优秀!