2023. 11. 20. 23:11 IT/C# 파헤치기
[C#][LINQ] 필터링 메소드 - OfType
참고 : https://learn.microsoft.com/ko-kr/dotnet/api/system.linq.enumerable.oftype
OfType
실행 | 쿼리문 | 메소드 |
지연된 실행 | 없음 | OfType |
사용예시
필터결과 = 집합.OfType<클래스>()
- 집합내의 아이템들 중 클래스에 해당하는 타입의 아이템들을 뽑아낸다.
OfType은 메소드로만 존재하고, 쿼리문은 없습니다.
예제 및 활용
기본적인 예
class Animal { } class Dog : Animal { } class Cat : Animal { } List<Animal> animals = new List<Animal>() { new Animal(), new Dog(), new Cat() }; // 주인공 OfType var res = animals.OfType<Dog>(); // 아래는 위 OfType과 동일한 로직을 Where과 일반 문법으로 표기한 겁니다. // where절일 때, var res = animals.Where(item => item.GetType() == typeof(Dog)); // 일반적인 문법일 때, foreach(var item in animals) { if(item.GetType() == typeof(Dog)) { } }
Animal을 상속받은 클래스 중에 Dog 클래스만을 필터링하는 코드입니다.
object가 최상위 클래스니까 object List에 여러 클래스를 담아서 원하는 클래스를 뽑아서 쓸 수도 있겠지만,, 그렇게 쓰는 곳이 있을런지 의문이네요.
특정 클래스를 상속받아 하나의 리스트에 담는 경우는 흔합니다. 같은 클래스를 상속받아 함수를 클래스별로 다르게 구현하고, list 루프를 돌면서 실행시키는 식으로 많이 쓰잖아요.
예를 들어, 모든 몬스터 (오크, 스켈레톤, 뱀파이어 등)를 이동시키고자 하는데, 다 이동범위가 제각각이라면, 최상이 클래스에 이동 함수를 구현하고, 각 몬스터마다 상속받아 이동범위를 다르게 구현하겠죠.
이 때 오크들만 뽑아서 잠깐 스톱시키고 싶다! 이럴 때 OfType으로 오크 클래스만 필터링해서 Stop 시킬 수 있겠네요.
다만, OfType은 Where절로도 구현이 가능합니다.
성능을 한번 PS에서 비교해보겠습니다.
PS. 성능 비교해보기.
1. foreach 와 Where절, OfType 비교하기.
코드 :
private void Start() { for(int i = 0; i < 100000; i++) { animals.Add(new Animal()); animals.Add(new Dog()); animals.Add(new Dog()); animals.Add(new Cat()); animals.Add(new Cat()); animals.Add(new Cat()); } Debug.Log("List count " + animals.Count); } public void OnClick1() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); foreach (var item in animals) { if (item.GetType() == typeof(Dog)) { } } sw.Stop(); Debug.Log($"foreach Time : {sw.ElapsedMilliseconds}ms"); } public void OnClick2() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); var res = animals.Where(item => item.GetType() == typeof(Dog)); foreach(var item in res) { } sw.Stop(); Debug.Log($"Where Time : {sw.ElapsedMilliseconds}ms"); } public void OnClick3() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); var res = animals.OfType<Dog>(); foreach (var item in res) { } sw.Stop(); Debug.Log($"OfType Time : {sw.ElapsedMilliseconds}ms"); }
결과:
상세 프로파일링 결과:
Foreach:
Where:
OfType:
결론:
foeach-if보다 where이 1.5배 정도 느리고, OfType 이 where보다 1.5배 정도 느리네요.
당혹스럽네요... Where로도 할 수 있는 걸 따로 메소드를 뺏길래 더 특화되서 좋은 건가? 했는데, 더 안좋네요?
뭔가 별도의 사용 용도가 있는 걸까요? 모르겠네요.
이전 where 절에서 테스트 했을 때는 foreach-if가 20~40배 가량 압도적으로 빨랐는데, 이번엔 1.5배가 나왔네요. 상황에 따라 다르긴 하지만 foreach-if가 Where절보다 빠르단 건 변하지 않았네요
(제대로 Type 필터 로직이 돌았는지는 count()를 통해 각각 200000의 결과가 나온건 확인했습니다. 프로파일링에서도 확인 할 수 있습니다.)
최종 결론:
- foreach-if (일반 문법) > Where > OfType 순으로 속도가 빠릅니다. ( OfType이 제일 느리고, 각각 1.5배 정도 이상의 차이가 난다.)
- OfType 전 안쓸랍니다...
테스트 환경
- cpu - i5-11400F
- gpu - GeForce RTX 3060
- Unity 2021.3.13f1
- VisualStudio 2022
'IT > C# 파헤치기' 카테고리의 다른 글
[C#][LINQ] 필터링 메소드 - Where (0) | 2023.11.19 |
---|---|
[C#][LINQ] 개요 및 목차 (0) | 2023.11.19 |
[C#]abstract 한정자 의미와 활용 (1) | 2018.04.10 |
[C#][뻘글] MS에서 말하는 코딩 규칙 (var 사용이유?) (0) | 2018.04.10 |
[C#] virtual 함수 의미 및 활용 (2) | 2018.04.04 |