OfType () или есть? - PullRequest
       0

OfType () или есть?

1 голос
/ 17 марта 2020

Допустим, у меня есть коллекция objs объектов разных типов, и я хочу проверить, есть ли хотя бы один элемент с указанным типом MyType. Какое решение лучше?

Решение 1:

bool found = objs.OfType<MyType>().Any();

Решение 2:

bool found = objs.Any(o => o is MyType);

Есть ли какая-либо разница?

Этот вопрос подходит не только для Any (), но и для других методов LINQ.

Ответы [ 2 ]

8 голосов
/ 17 марта 2020

Ради интереса я собрал тест, используя BenchmarkDo tNet:

public class MyType { }
public interface IMyType { }
public struct MyStruct { }

namespace Benchmark
{
    public class MyBenchmark
    {
        private readonly List<object> classes = new List<object>();
        private readonly List<MyStruct> structs = new List<MyStruct>();

        public MyBenchmark()
        {
            for (int i = 0; i < 100; i++)
            {
                classes.Add(new object());
                structs.Add(new MyStruct());
            }
        }

        [Benchmark]
        public bool OfTypeClass()
        {
            return classes.OfType<MyType>().Any();
        }

        [Benchmark]
        public bool AnyClass()
        {
            return classes.Any(x => x is MyType);
        }

        [Benchmark]
        public bool OfTypeStruct()
        {
            return structs.OfType<IMyType>().Any();
        }

        [Benchmark]
        public bool AnyStruct()
        {
            return structs.Any(x => x is IMyType);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<MyBenchmark>();
        }
    }
}

С результатами:

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18363
Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.1.200-preview-014883
  [Host]     : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
  DefaultJob : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT

|       Method |       Mean |    Error |   StdDev |
|------------- |-----------:|---------:|---------:|
|  OfTypeClass | 1,697.2 ns | 29.92 ns | 27.98 ns |
|     AnyClass | 1,477.2 ns | 18.77 ns | 14.65 ns |
| OfTypeStruct | 1,895.0 ns | 37.45 ns | 60.48 ns |
|    AnyStruct |   820.6 ns | 13.57 ns | 11.33 ns |

Мы видим, что Any немного быстрее, чем OfTypeOfType немного дороже для структур, как и ожидалось, потому что он должен их упаковать), но в этом нет особого значения.

Что любопытно, так это AnyStruct намного быстрее. Я предполагаю, что JIT смог обнаружить, что MyStruct не реализует IMyType, и значительно оптимизировать вещи.

5 голосов
/ 17 марта 2020

Если мы посмотрим на исходный код OfType () (https://github.com/microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs), мы увидим

    public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source) {
        if (source == null) throw Error.ArgumentNull("source");
        return OfTypeIterator<TResult>(source);
    }

    static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source) {
        foreach (object obj in source) {
            if (obj is TResult) yield return (TResult)obj;
        }
    }

Итак, в принципе, они одинаковы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...