Search code examples
c#ienumerable

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?


Solution

  • 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;