I have the current function:
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);
}
}
}
}
It:
- Parse all subkeys of a registry key
- For each subkeys, parse all of its values
- If the value is a string, adds it to the iterator
My concern is that there's two embedded for-each loops, which I do not like at all. I'd like to split this function in two.
The problem is that I end up in the end with a return type of IEnumerable<IEnumerable<string>>
I tried to build the Iterator in the second function only, and directly return it in the first, but doing this I miss all the subsequent calls.
This is the code that caused it:
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);
}
}
}
How would you do that ?
Edit:
I have this solution so far, but could it be improved ?
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);
}
}
}
CodePudding user response:
I have this solution so far, but could it be improved ?
Your solution is fine. If you want more compact code, you can use the LINQ method SelectMany
, whose purpose is to "flatten" an IEnumerable<IEnumerable<T>>
into an IEnumerable<T>
:
private IEnumerable<string> GetSubKeysStringValues(RegistryKey key)
{
return GetAllSubKeys(key).SelectMany(subKey => GetKeysStringValues(subKey));
}
...or, if you prefer query syntax (yields the same result and probably even the same IL code):
private IEnumerable<string> GetSubKeysStringValues(RegistryKey key)
{
return from subKey in GetAllSubKeys(key)
from value in GetKeysStringValues(subKey)
select value;
}