Reputation: 49599
What would be the shortest notation to find the first item that is of a certain type in a list of elements using LINQ and C#.
Upvotes: 25
Views: 17478
Reputation: 591
I recommend hugoware's answer, to avoid unnecessary iterations:
(string)source.FirstOrDefault(f => f is string)
But if you worry about micro optimizations, you could create your own extension method:
public static class ListExtensions
{
public static T FirstOrDefault<T>(this IList source)
{
for (int i = 0; i < source.Count; i++)
{
if (source[i] is T)
return (T)source[i];
}
return default;
}
}
Benchmarks using a 100 objects lists where only the last one is a string (dotnet 7, BenchmarkDotNet):
[Benchmark]
public string OfType_First() => objects.OfType<string>().FirstOrDefault();
[Benchmark]
public string FirstOrDefault() => (string)objects.FirstOrDefault(f => f is string);
[Benchmark]
public string FirstOrDefault_T() => objects.FirstOrDefault<string>();
| Method | Size | Mean | Error | StdDev | Allocated |
|----------------- |----- |-----------:|---------:|----------:|----------:|
| OfType_First | 100 | 1,229.0 ns | 57.86 ns | 157.41 ns | 96 B |
| FirstOrDefault | 100 | 920.1 ns | 18.31 ns | 31.59 ns | 40 B |
| FirstOrDefault_T | 100 | 671.4 ns | 12.24 ns | 15.91 ns | - |
// * Legends *
Size : Value of the 'Size' parameter
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
1 ns : 1 Nanosecond (0.000000001 sec)
Upvotes: 0
Reputation: 36397
You could just use the FirstOrDefault
and pass in the delegate to use for the comparison.
object[] list = new object[] {
4,
"something",
3,
false,
"other"
};
string first = list.FirstOrDefault(o => o is string); //something
Upvotes: 6
Reputation: 269278
var first = yourCollection.OfType<YourType>().First();
Note that the First
method will throw an exception if there are no elements of type YourType
. If you don't want that then you could use FirstOrDefault
or Take(1)
instead, depending on the behaviour you do want.
Upvotes: 39
Reputation: 790
Use the OfType extension method:
public static T FindFirstOfType<T>(IEnumerable list){
return list.OfType<T>().FirstOrDefault();
}
Upvotes: 15