본문 바로가기

개발 공부 유니티, C#/스터디

Effective C# Chapter 1

IEnumerator, IEnumerable, foreach, yield, 지연 처리

IEnumerator 열거자를 구현하는 인터페이스

IEnumerable 열거자 IEnumerator를 Get하기 위한 인터페이스

 

C#의 모든 Collections 컬렉션은 IEnumerable, IEnumerator를 상속받아 구현하고 있다.

그래서 List, Array 같은 컬렉션 클래스 객체들을 foreach문에서 돌릴 수 있는 것!

 

객체로 foreach문을 돌리기 위해서는 그 객체 타입이 IEnumerable을 상속받은 클래스여야 한다.

foreach는 객체의 GetEnumerator() 함수를 통해 열거자 IEnumerator 객체를 리턴 받고 이를 통해 데이터를 순회한다.

IEnumerable을 상속받아 GetEnumerator()을 구현한 클래스이어야 foreach로 내부 데이터를 열거할 수 있다.

 

IEnumerator는 안에서 순회하는 객체(지연 처리시 다음 시작할 위치를 여기서)

Enumerable을 구현한 클래스에서 foreach문으로 순회하다 특정값을 IEnumerator(GetEnumerator)로 반환

 

yield는 IEnumerator/ IEnumerable 의 간편표기법이다. (둘중 아무거나 될 수 있음)

반환형이 IEnumerable인 함수에 yield return x; yield break; 가능 

 

Manager, packet handler, class 간의 관계가 독립적일수록 좋음

 

아이템 3 캐스트보다 is as 사용

타입 캐스팅에 실패하면 익셉션 발생

is/as를 쓰면 반환형이 null인지만 확인 하면 됨

 

as를 쓸수 없는 경우

값 타입 as 참조타입 //컴파일 에러(값 타입이 null이 될수 없기때문)

 

아이템 4 string.Format() 말고 보간 문자열 사용
보간 문자열  : 값을 문자열 상에서 표현하는 방식들 소수점 자릿수 단위 등

{0:f2} //string.Format 숫자 형식
{0:00} //소수 자릿수 표현 

{0:#,###} //정수만 표현
{0:D4} //단위, 추가
{0001} //최소표현 자릿수

string.Format("{0:P}", 0.2189); //21.89 % //백분율 표현
string.Format("{0:P1}", 0.2189); //21.8 %

 

보간 문자열은 object타입으로 반환하기 때문에 ToString()사용 해야함

박싱 일어날 수 있음

 

아이템 6 nameof() 연산자 사용

Console.WriteLine(MyEnum.SECOND.ToString());
Console.WriteLine(nameof(MyEnum.SECOND));

변수명을 출력

로컬명으로 찍음(MyEnum.SECOND가 아닌 SECOND가 찍힘)

위처럼 쓰면 런타임에 작동해서 느림

nameof를 사용하면 컴파일 타임에 작동

 

아이템 7 콜백 델리게이트

델리게이트 체인에서 반환값이 있는경우 마지막 반환값외에 다른값은 모두 무시됨

foreach로 반환값이 있는 델리게이트를 돌려서 처리가능

Func<T>, Action<T>, Predicate<T> 

 

아이템 8

Updated?.Invoke(this, counter);

널체크 + 멀티 쓰레딩 환경에서 안전함

 

 

 

 

 

 

내 개발엔 해당 안됬던 내용 + 뻔한 내용들

 

아이템 1.지역변수에 var 선언

3반환타입이 IEnumerable<T> IQueryable<T> 인지에 따라 성능차이 심함

IEnumerable<T>는 로컬에서 작업

IQueryable<T>는 DB에서 작업

linq sql문을 사용한 결과로 IQueryable타입을 반환하는데, 이 경우 데이터 추출, 정렬까지 모두 DB에서 수행

 

IEnumerable은 쿼리식 내의 람다와 매개변수를 나타내기 위해 델리게이트를 사용

Enumerable내의 모든 함수는 로컬에서 수행

데이터를 모두 로컬로 가져오고 나중에 제거

 

IQueryable은 표현식 트리를 사용

필요한 데이터를 데이터가 있는 위치에서 추출후 로컬로 받음

 

*아직까지는 로컬에 파싱된 데이터들을 가지고만 조작해봐서 이 내용이 프로젝트에서 흔히 쓰는 방식에서 성능 향상이 있을지 잘 모르겠음.

 

부적절한 경우

런타임에 타입이 적용되거나, 숫자 연산시 추론하기 힘든 타입에 사용하기 부적절



아이템 2 const 보다 readonly 사용

const, readonly의 차이

컴파일타임, 런타임

값타입, 참조타입

readonly는 인스턴스 별로 다른 값을 가질 수 있음 => 안하는게 좋을 것 같음.

switch문의 레이블, enum은 const만 가능

값의 변화가 생겼을 때 const는 전체 재빌드  readonly는 해당 Infrastructure파일(특정 DLL)만 배포

이지만 유니티 프로젝트는 결국 전체 재빌드 해야했음

 

아이템5 FormattableString으로 국가별 문자열 대응

이거보단 디파인이 더 좋지 않은지..

 

아이템9 박싱 언박싱

값타입 <-> 참조타입

기본 컬렉션 ArrayList등은 정해진 타입이 없기 때문에 추가시 마다 박싱/언박싱이 일어난다.

List의 Find, RemoveAll 등 내부 함수들은 델리게이트로 구성되어있음

 

아이템10 new..한정자..

override 안쓰고 사용할 일이있는지 모르겠음

upcasting된 경우 override와는 달리 부모의 함수호출

부모가 업그레이드 된경우라는것도 잘 모르겠음