Find run with specific text in it

I have this to find runs with text that starts with #, but I get an empty sequence back:

IEnumerable<Run> runs = doc.Descendants<Run>().
     Where<Run>(r => r.Descendants<Text>().First<Text>().Text[0] == '#');

This cannot be right because the following gives me 4 results:

IEnumerable<Text> t = doc.Descendants<Text>().
       Where<Text>(txt => txt.Text[0] == '#');

What do I do wrong?

Jon Skeet
people
quotationmark

Well your first snippet only gives runs whose first text descendant starts with #. Your second snippet gives all text descendants starting with #. So if you've got any runs with a non-first text descendant starting with #, that will be counted in the second snippet but not the first...

It's unclear which behaviour you actually want, but if you do want to find every run containing a text element starting with #, just change your first snippet to:

IEnumerable<Run> runs = doc
    .Descendants<Run>()
    .Where<Run>(r => r.Descendants<Text>()
                      .Any<Text>(text => text.Text[0] == '#'));

If you're still surprised that the two snippets give you different results, you could easily check that:

foreach (var run in doc.Descendants<Run>())
{
    Console.WriteLine("Run!");
    foreach (var textElement in run.Descendants<Text>())
    {
        string text = textElement.Text;
        Console.WriteLine("- {0}", text.Substring(0, Math.Min(5, text.Length)));
    }
}

(I haven't used this object model for a long time, by the way - so you should also check whether there are things like nested runs.)

people

See more on this question at Stackoverflow