I want to extract two foreach´s which iterate over mostly the same list but one has an early exit if one element is not valid and the other will only be executed if the other collected the data correctly. Therefor I want to use the iterator-pattern.
Thats a scheme of the use case:
foreach (var material in matrix.Materials)
{
var validationResult = materialValidator.Validate(material);
if (validationResult.IsValid == false)
{
return;
}
validMaterials.Add(
new Tuple<IMaterial, string>(
materialValidator.CurrentMaterial,
material.TextMask));
}
foreach (var tuple in validMaterials)
{
var material = tuple.Item1;
var text = tuple.Item2;
material.SetSelcted(true);
if (string.IsNullOrWhiteSpace(text) == false)
{
module.SetTextMask(textMask);
}
}
But what I want is to iterate the enumerable if there are valid materials e.g:
var enumerable = new MaterialsEnumerable(matrix.Materials)
foreach (var iterator in enumerable)
{
iterator.Material.SetSelcted(true);
if (string.IsNullOrWhiteSpace(iterator.Text) == false)
{
module.SetTextMask(iterator.Text);
}
}
And the implementation of MaterialsEnumerable so good as follows, with one missing detail: how do I yield return an empty enumerable at one path?
public IEnumerator<MaterialIterator> GetEnumerator()
{
foreach (var material in this.materials)
{
var result = this.validator.Validate(material);
if (result.IsValid == false)
{
return Enumerable.Empty<MaterialIterator>(); // <- this doesn´t work
}
yield return new MaterialIterator(
this.validator.CurrentMaterial,
material.TextMask);
}
}
My Solution is to yield break if one element is invalid: