Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在类委托的哪个实例上被调用?_C#_Events_Delegates - Fatal编程技术网

C# 在类委托的哪个实例上被调用?

C# 在类委托的哪个实例上被调用?,c#,events,delegates,C#,Events,Delegates,考虑一下这个代码 public class A { //... void f() { B b = new B(); b.SomeEvent += this.SomeMethod; } void SomeMethod() {} } public class B { //... public event SomeEventHandler SomeEvent; voi

考虑一下这个代码

public class A
{
     //...
     void f()
     {  
          B b = new B();
          b.SomeEvent += this.SomeMethod;
     }
     void SomeMethod() {}
 }

 public class B
 {
     //...

     public event SomeEventHandler SomeEvent;

     void h()
     {  
          if ( SomeEvent != null )
          {
               SomeEvent.invoke();
          }
     }
 }
在这个代码段中,
SomeEvent.invoke()
实际上调用了类
A
SomeMethod()
。所以在这一点上,我有几个问题:

  • A
    的哪个实例上调用
    SomeMethod
    B
    如何知道要在哪个实例上调用委托?CLR在这里是如何工作的
  • 而且,
    SomeMethod
    是一个私有方法,那么为什么
    B
    能够从类
    a
    之外调用这个方法呢
编辑:

在阅读了前面的几个答案后,我知道
Delegate
有一个
Target
属性,在该属性上可以调用Delegate。但我无法真正理解这个
Target
属性设置的具体步骤是什么?谁定的?当我写
b.SomeEvent+=this.SomeMethod时
,它是否也设置了
目标
属性?具体如何?

  • 附加到事件时使用的任何实例
  • 因为
    A
    在类外向其传递了一个委托表示

特定的
委托
实例具有
目标
属性;这表示调用委托时将使用的实例

委托包含调用方法的目标引用。您可以使用
Delegate.Target
属性检查这一点。在这种情况下,将在调用
f
的实例上调用它。(如果调用的是静态方法,则为null。)

至于隐私,这只是代表们的特点之一。您只能在有权访问私有方法的代码中创建委托,但可以在任何地方运行它。可以将其视为通过从公共接口实现中调用私有方法来实现接口

在SomeMethod的哪个实例上被调用?B如何知道要在其上调用委托的实例?CLR在这里是如何工作的

委托实际上包含对实际实例的引用。这将导致它在调用它的特定实例上调用

另外,SomeMethod是一个私有方法,那么为什么B能够从类a之外调用这个方法呢

它不直接执行方法,而是执行委托。这里有一个区别-私有约束只应用于方法,但是由于类本身创建委托,它可以访问方法,所以一切都正常

 b.SomeEvent += this.SomeMethod
这里有很多糖,阻止你看到真正发生的事情。写出来后,它类似于:

 b.SomeEvent.add(new MulticastDelegate(this, SomeMethod));     // not legal code
其中add()是事件的add访问器,当您不显式声明自己的访问器时,编译器会自动生成一个。委托构造函数的第一个参数是您询问的对象实例,即委托对象的目标属性。请注意,这会产生副作用,事件订阅会保留对
b
对象的引用。这会阻止它被垃圾收集,这在调用事件时会非常糟糕


这也可能是一个问题,您可能会无意中泄漏对象引用。您的代码中没有取消订阅事件处理程序的好方法,因此A对象将与调用h()的B对象一样存在。

Jon:我编辑了我的问题。请看编辑。顺便说一句,我买了你的书,也许你还记得我订书时告诉你的。所以,如果你在书中讨论过这件事,请务必告诉我这一章/章节,以便我自己详细阅读。@Nawaz:第二章有很多关于代表的内容,是的。享受:)哈哈……现在我正在看
2.2.2节,什么时候C#1的类型系统不够丰富?
。谢谢你写了这么好的一本书。也许你已经猜到这本书让我问了这个问题。也许,我应该有点耐心!最后一篇帖子……这告诉了我一些我一直在寻找的东西+1.