Building an external list while filtering in LINQ

Posted by Khnle on Stack Overflow See other posts from Stack Overflow or by Khnle
Published on 2010-03-29T02:53:18Z Indexed on 2010/03/29 3:33 UTC
Read the original article Hit count: 275

Filed under:

I have an array of input strings that contains either email addresses or account names in the form of domain\account. I would like to build a List of string that contains only email addresses. If an element in the input array is of the form domain\account, I will perform a lookup in the dictionary. If the key is found in the dictionary, that value is the email address. If not found, that won't get added to the result list. The code below will makes the above description clear:

private bool where(string input, Dictionary<string, string> dict)
{
    if (input.Contains("@"))
    {                
        return true;
    }
    else
    {
       try
       {
           string value = dict[input];             
           return true;
       }
       catch (KeyNotFoundException)
       {
           return false;
       }
    }
}

private string select(string input, Dictionary<string, string> dict)
{
    if (input.Contains("@"))
    {                
        return input;
    }
    else
    {
        try
        {
            string value = dict[input];                    
            return value;
        }
        catch (KeyNotFoundException)
        {
            return null;
        }
    }
}
public void run()
{
    Dictionary<string, string> dict = new Dictionary<string, string>()
    {
        { "gmail\\nameless", "[email protected]"}
    };    

    string[] s = { "[email protected]", "gmail\\nameless", "gmail\\unknown" };
    var q = s.Where(p => where(p, dict)).Select(p => select(p, dict));
    List<string> resultList = q.ToList<string>();
}

While the above code works (hope I don't have any typo here), there are 2 problems that I do not like with the above:

  1. The code in where() and select() seems to be redundant/repeating.
  2. It takes 2 passes. The second pass converts from the query expression to List.

So I would like to add to the List resultList directly in the where() method. It seems like I should be able to do so. Here's the code:

private bool where(string input, Dictionary<string, string> dict, List<string> resultList)
{
    if (input.Contains("@"))
    {                
        resultList.Add(input);  //note the difference from above
        return true;
    }
    else
    {
       try
       {
           string value = dict[input];
           resultList.Add(value); //note the difference from above             
           return true;
       }
       catch (KeyNotFoundException)
       {
           return false;
       }
    }
}

The my LINQ expression can be nicely in 1 single statement:

List<string> resultList = new List<string>();
s.Where(p => where(p, dict, resultList));

Or

var q = s.Where(p => where(p, dict, resultList)); //do nothing with q afterward

Which seems like perfect and legal C# LINQ. The result: sometime it works and sometime it doesn't. So why doesn't my code work reliably and how can I make it do so?

© Stack Overflow or respective owner

Related posts about LINQ