Efficient use of LINQ - Indexing I have a Class with a List of objects, and those objects contain a list which has lists to objects in the first class, and I'm trying to quickly index them.  Simplified:

class Person
{
    public IEnumberable&lt;HistoricalEvent&gt; Events
    {
        get
        {
            return World.HistoricalEvents.Values.Where(x=&gt;x.PeopleInvolved.Contains(this));
        }
    }
}


Also

class HistoricalEvent
{
    public virtual IEnumerable&lt;HistoricalFigure&gt; PeopleInvolved
    {
        get { return Enumerable.Empty&lt;People&gt;(); }
    }
...
}


and a subclass

class HistoricalEventSubclass : HistoricalEvent
{
    Person person1 = new Person("Alice");
    Person person2 = new Person("Bob");        

    public override IEnumerable&lt;Person&gt; PeopleInvolved
    {
        get
        {
            yield return person1;
            yield return person2;
        }
    }       
    ...
}


The Events class is called from a method using: frm.grpHistoricalFigureEvents.FillListboxWith(frm.lstHistoricalFigureEvents, Events);

    internal static void FillListboxWith(this GroupBox groupbox, ListBox listbox, IEnumerable&lt;object&gt; objects)
    {
        if (objects == null || !objects.Any())
        {
            groupbox.Visible = false;
            return;
        }
        groupbox.Visible = true;
        listbox.BeginUpdate();
        listbox.Items.Clear();
        listbox.Items.AddRange(objects.ToArray());
        listbox.EndUpdate();
        listbox.SelectedIndex = 0;
        var title = groupbox.Text.Split('(')[0].Trim();
        groupbox.Text = string.Format("{0} ({1})", title, listbox.Items.Count);
    }


The problem is that calling Events takes a long time (as World.HistoricalEvents can be a very big List).  Is there a more time-efficient way of doing this?

Part of the slowdown is that Events is converted ToArray() and shoved into a listbox, and so I'll also be pursuing an alternative such as a listbox which can handle an IEnumberable directly.
How do you load the data for events and people? If you can denormalise your data so that a person has a materialised Set/List of events they are involved in I suspect you would gain a lot of performance (at the cost of a bit of memory).

Here is some pseudo code to explain what I mean:

var personStore = new Dictionary&lt;string, Person&gt;();
var eventStore = new Dictionary&lt;string, Event&gt;();
foreach (var eventData in eventSource)
{
  var event = new Event(eventData);
  eventStore[eventData.Name] = event;

  foreach (var personData in eventData)
  {
    // Is this the first time we've seen this person?
    if (!personStore.HasKey(personData.Name)
    {
      personStore[personData.Name] = new Person(personData);
    }

    var person = personStore[personData.Name];

    // This creates the bidirectional mapping which makes lookups
    // in either direction fast.
    event.PeopleInvolved.Add(person);
    person.Events.Add(event);
  }  
}