1

我在 .NET 4 中有一个基于集合的项目。我的意思是,我有一个主集合,称之为“系统”,它由框架组成,每个框架都由卡片组成,卡片依次制作频道。所以,它看起来像 System->Frame->Card->Channel。所有这些都表示为对象,并且它们之间存在父子关系。本质上,Channel 只暴露给 Card,Card 只暴露给 Frame,Frame 只暴露给 System。

理想情况下,我希望仅将 System 类中的方法公开给外界。但是,在 Channel、Card 和 Frame 类中会发生一些关键事件。目前,我处理它们的方式是通过传播。假设 Channel 中发生了一个事件。此事件首先在 Card 中引发,然后在 Frame 中引发,最后在 System 中引发。您可以看到这是如何产生大量代码的。但我主要关心的不是代码,而是性能。

你认为这种传播会严重影响我的表现吗?有没有办法让它更有效率?我还有什么其他选择?我的收藏比较少。System 为 1,Frames < 16,Cards < 256,Channels < 8192。大部分数据存储在 Channel 类中,其中只有原始对象。

编辑

这是我在 Card 中针对 Channel 引发的事件的代码:

protected virtual void OnChannelPropertyChanged(Object sender, PFPropertyChangedEventArgs e)
    {
        try
        {
            EventHandler<PFPropertyChangedEventArgs> handler = ChannelPropertyChanged;
            TestEventArgs_ChannelPropertyChanged = e;
            if (handler != null)
            {
                handler(sender, e);
            }
        }
        catch (Exception ex)
        {
            Milltown.MTCore.mtException mtEx = new Milltown.MTCore.mtException((int)PFExceptions.Exception_Hidden_FuctionLevel, ex,
            PFCommonVariables.ApplicationPlatform, PFCommonVariables.ApplicationDataSource, "PFCard:OnChannelPropertyChanged");
        }
    }

当我在 Card 类中将 Channel 添加到 Card 时,我调用:

channel.ChannelPropertyChanged += this.OnChannelPropertyChanged;
4

2 回答 2

3

您可以在 System 类中执行此操作:

event EventHandler FrameEvent
{
    add { this.frame.FrameEvent += value; }
    remove { this.frame.FrameEvent -= value; }
}

所以如果客户这样做

system.FrameEvent += Handler;

处理程序实际上附加到 Frame 类中的 Event。

于 2010-07-20T15:23:25.970 回答
2

回答是否影响您的性能的唯一方法是对其进行测试:尝试一种传播事件的方式,然后尝试另一种直接附加的方式。看看哪个更快。

话虽如此,我无法想象当您有几个连续的委托调用而不是一个时,您会发现对性能有很多(如果有的话)可衡量的影响。是的,委托调用比实际方法稍慢,因此,在所有条件相同的情况下,添加更多间接级别比使用常规方法调用的相同级别具有更大的影响,但这有过早优化的味道。

如果有人问你如何做你所追求的,我会推荐你​​的方法。除非有问题,否则就去吧。

编辑

为了回应您对另一个答案的评论,我想扩展。C# 事件具有所谓的“属性语法”。如果在一个类中显式实现,它看起来像这样:

private EventHandler eventDelegate;

public event EventHandler MyEvent
{
    add { eventDelegate += value; }
    remove { eventDelegate -= value; }
}

(实际上,它使用Delegate.Combine,但这在这里无关紧要)

当您附加到一个事件时,它实际上会调用add代码,将委托传递给附加为value; 也是如此remove

当您使用这样的速记事件语法时:

public event EventHandler MyEvent;

它实际上生成的代码与我上面发布的非常相似。但是,如果你明确表示,你可以在addremove处理程序中做任何你喜欢的事情。这意味着您可以将目标委托重定向到其他地方。在另一个答案的情况下,它将委托重定向到子对象。

当且仅当满足以下条件时,这将起作用:

  1. 父子关系1:1,关联对象不变
  2. 公开对子对象(as object)的引用是可以接受的

如果您有多个孩子,这在技术上是可行的(您可以循环并附加到所有孩子并在 中add删除所有孩子remove),但管理起来要困难得多。如果相关对象或对象集合在事件附加后可以更改,则几乎不可能进行协调。

此外,如果您的事件遵循事件的推荐做法(您将触发对象作为 传递sender),那么因为您将目标直接附加到子事件而不是自己引发它,那么您将公开对通过这个参数的子对象。我不知道这对您是否相关或可以接受,但这是应该考虑的事情

于 2010-07-20T15:14:31.307 回答