Can IEnumerable.Select() skip an item?

I have this function:

public IEnumerable<string> EnumPrograms() {
    return dev.AudioSessionManager2.Sessions.AsEnumerable()
        .Where(s => s.GetProcessID != 0)
        .Select(s => {
            try {
                return Process.GetProcessById((int)s.GetProcessID).ProcessName;
            }
            catch (ArgumentException) {
                return null;
            }
        });
}

The try..catch is necessary since there may be sessions with a PID that doesn't exist anymore. I'd like to skip them. Is there a way to do this from the Select callback or do I need to add a new Where condition that skips null values?

Jon Skeet
people
quotationmark

No, Select always yields one output element for each input element. There's no alternative to that. You could easily write your own FilteredSelect extension method - but it's simpler just to use a Where clause.

Alternatively, use Process.GetProcesses() to get a snapshot of all processes, and then join that to your sessions collection (or use something similar). That would avoid the ugly catch:

var sessionProcessIds = new HashSet<int>(dev.AudioSessionManager2.Sessions
                                            .AsEnumerable()
                                            .Select(x => x.GetProcessId)
                                            .Where(pid => pid != 0));
var processes = Process.GetProcesses();
var sessionProcessNames = processes.Where(p => sessionProcessIds.Contains(p.Id))
                                   .Select(p => p.ProcessName);

Or:

var names = from session in dev.AudioSessionManager2.Sessions.AsEnumerable()
            let pid = session.GetProcessId
            where pid != 0
            join process in Process.GetProcesses() on pid equals process.Id
            select process.ProcessName;

people

See more on this question at Stackoverflow