在两个不同的函数中拆分包含两个 foreach 循环的迭代器

Split an Iterator containing two foreach loops in two different functions

我有当前函数:

private IEnumerable<string> GetKeysStringValues(RegistryKey key)
{
    foreach (var subKey in GetAllSubKeys(key))
    {
        foreach (var value in subKey.GetValueNames())
        {
            if (subKey.GetValueKind(value) == RegistryValueKind.String)
            {
                yield return (string) subKey.GetValue(value);
            }
        }
    }
}

它:

  1. 解析注册表项的所有子项
  2. 对于每个子项,解析其所有值
  3. 如果值为字符串,则将其添加到迭代器

我担心的是有两个嵌入式 for-each 循环,我一点也不喜欢。 我想把这个功能一分为二。

问题是我最终得到了 return 类型的 IEnumerable<IEnumerable<string>>

我试图只在第二个函数中构建迭代器,并在第一个函数中直接 return 它,但是这样做我错过了所有后续调用。

这是导致它的代码:

    private IEnumerable<IEnumerable<string>> GetSubKeysStringValues(RegistryKey key)
    {
        IEnumerable<string> enumerable = Enumerable.Empty<string>();
        
        foreach (var subKey in GetAllSubKeys(key))
        {
            yield return GetKeysStringValues(subKey));
        }
    }

    private IEnumerable<string> GetKeysStringValues(RegistryKey key)
    {
        foreach (var value in key.GetValueNames())
        {
            if (key.GetValueKind(value) == RegistryValueKind.String)
            {
                yield return (string) key.GetValue(value);
            }
        }
    }

你会怎么做?

编辑:

到目前为止我有这个解决方案,但它可以改进吗?

private IEnumerable<string> GetSubKeysStringValues(RegistryKey key)
{
    IEnumerable<string> enumerable = Enumerable.Empty<string>();
    
    foreach (var subKey in GetAllSubKeys(key))
    {
        enumerable = enumerable.Concat(GetKeysStringValues(subKey));
    }

    return enumerable;
}

private IEnumerable<string> GetKeysStringValues(RegistryKey key)
{
    foreach (var value in key.GetValueNames())
    {
        if (key.GetValueKind(value) == RegistryValueKind.String)
        {
            yield return (string) key.GetValue(value);
        }
    }
}

I have this solution so far, but could it be improved ?

你的解决方案很好。如果您想要更紧凑的代码,可以使用 LINQ 方法 SelectMany,其目的是将 IEnumerable<IEnumerable<T>>“扁平化”为 IEnumerable<T>:

private IEnumerable<string> GetSubKeysStringValues(RegistryKey key)
{
    return GetAllSubKeys(key).SelectMany(subKey => GetKeysStringValues(subKey));
}

...或者,如果您更喜欢查询语法(产生相同的结果,甚至可能产生相同的 IL 代码):

private IEnumerable<string> GetSubKeysStringValues(RegistryKey key)
{
    return from subKey in GetAllSubKeys(key)
           from value in GetKeysStringValues(subKey)
           select value;
}