I have a method that finds all of a specific value in an IEnumerable
source and returns the value and index. At this time, I want to return the default
value when there is no matching value, but I don't know how.
This is because you are using yield return
instead of creating and returning a new collection like List<T>.FindAll()
.
public static class Example
{
public static IEnumerable<(T sought, int index)> FindAllOccurrence<T>(
this IEnumerable<T> source, T value)
{
if (source == null)
throw new ArgumentNullException(nameof(source), "The argument is null");
if (value == null)
throw new ArgumentNullException(nameof(value), "The argument is null");
foreach (var pair in source.Select((e, i) => (e, i)))
{
if (pair.e.Equals(value))
{
yield return (pair.e, pair.i);
}
}
// How do I use the if statement here?
yield return (default(T), -1);
}
}
When the code below is written, the statement yield return (default(T), -1);
is also executed.
public static void Operation()
{
var list = new List<int>
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3, 3, 3
};
var enumerable = list.FindAllOccurrence(3);
foreach (var (value, index) in enumerable)
{
Console.WriteLine($"value: {value}, index: {index}");
}
}
How do I write a proper if statement to prevent that statement from being executed?
CodePudding user response:
You want DefaultIfEmpty
:
public static IEnumerable<(T sought, int index)> FindAllOccurrence<T>(
this IEnumerable<T> source, T value)
{
if (source == null)
throw new ArgumentNullException(nameof(source), "The argument is null");
if (value == null)
throw new ArgumentNullException(nameof(value), "The argument is null");
return source.Where(e => e.Equals(value)).Select((e, i) => (e, i)).DefaultIfEmpty((default(T), -1));
}
I'd also write this as:
public static IEnumerable<(T sought, int index)> FindAllOccurrence<T>(
this IEnumerable<T> source, T value) =>
source
.Where(e => e.Equals(value))
.Select((e, i) => (e, i))
.DefaultIfEmpty((default(T), -1));
You get an exception already if source
is null
and it's not clear to me that you should get an exception if value
is null
.
If you want a direct answer to your question, here's how:
public static IEnumerable<(T sought, int index)> FindAllOccurrence<T>(
this IEnumerable<T> source, T value)
{
if (source == null)
throw new ArgumentNullException(nameof(source), "The argument is null");
if (value == null)
throw new ArgumentNullException(nameof(value), "The argument is null");
var found = false;
foreach (var pair in source.Select((e, i) => (e, i)))
{
if (pair.e.Equals(value))
{
found = true;
yield return (pair.e, pair.i);
}
}
if (!found)
yield return (default(T), -1);
}
CodePudding user response:
wouldn't you create the default value here? What is the default value you want? yield return ((T)Convert.ChangeType(88, typeof(T)), -1);
default value is 0, but you can change it to what you want. However it has to be of type Int