람다 식 (Lambda Expression)

미적분학 형태에서 (x) => x * x 와 같이 화살표가 들어간 표기법을 사용해 함수를 표현하는데

람다식의 개념은 바로 이 함수를 설명하는 표현 방법을 제공하는 "Lambda Calculas"에 기원을 둔다.

람다 식은 대리자 또는 식 트리 형식을 만드는 데 사용할 수 있는 일종의 익명 함수이다.

람다 식을 사용하여 인수로 전달하거나 호출에 대한 값을 반환하는 로컬 함수를 쓸 수 있다.


둘 이상의 입력 매개변수 사용 예제 (x, y) => x == y  괄호로 묶고 쉼표로 구분


Lambda (문 형태 람다) 예시 (input-parameter) => { statement; } 중괄호 안에 문을 지정한다.



 namespace System에서 미리 선언해 둔 Func Actioin 을 사용하면 델리게이트 선언 없이 바로 람다 식을 사용할 수 있다



Func<T1, TResult> 예시  String.Split (문자열 분할 구문 사용) 메서드

크리스마스

12

25

2018


Func<T1, T2, TResult> 예시 Select 메서드  

the

same


Lambda 쿼리문 예시 Count 메서드

62 35 32 26 67 42 51 12 70

커트라인 점수 [50]을 넘긴 학생 수: 4


Lambda (문 형태 람다) 예시

4

6


'Programming > C++, C#' 카테고리의 다른 글

[C#] Generic  (0) 2018.06.06
[C#] IEnumerator  (0) 2018.06.06
[C#] Interface  (0) 2018.06.06
[C#] Delegate , Event  (0) 2018.06.06
[C#] Out vs Ref  (0) 2018.06.06


제네릭 (Generic)


미결정 상태의 데이타 타입을 클라이언트 코드에서 클래스 또는 메서드로 선언하고 인스턴스화할 때

지정하는 유연한 타입 지정방식이다. (.NET Framework버전 2.0 이후 형식 매개변수(Type Parameter)라는 개념으로 새롭게 도입되었다.)


제네릭 도입 이전에는 일반화된 알고리즘을 정의하기 위해서 모든 멤버들을 object 데이터 타입으로 다루어야만 했다.

값 타입의 객체를 object 데이터 타입으로 전달 할 때 내부적으로 박싱이 수행되는데 

이것은 Garbage Collection을 유발하므로 성능에 악영향을 미치게 된다.

제네릭 알고리즘을 이용하면 원하는 타입을 지정하여 값 타입의 인스턴스를 참조 형태(by reference)가 아닌 

값 그 자체(by Value)로 전달할 수 있으므로 내부적으로 더이상 박싱을 수행하지 않아도 된다. 


제네릭 example (swap)

output :

100 and 200

200 and 100

유니티 and 언리얼

언리얼 and 유니티

(0.0, 0.0) and (3.0, 9.0)

(3.0, 9.0) and (0.0, 0.0)


형식 매개변수를 두 개 사용하는 새로운 클래스를 만들어서 사용해보자.

output:

상품 :weapon 가격 :450 상품 :potion 가격 :100

상품 :potion 가격 :450 상품 :weapon 가격 :100


'Programming > C++, C#' 카테고리의 다른 글

[C#] Lambda Expression  (0) 2018.06.07
[C#] IEnumerator  (0) 2018.06.06
[C#] Interface  (0) 2018.06.06
[C#] Delegate , Event  (0) 2018.06.06
[C#] Out vs Ref  (0) 2018.06.06

IEnumerable 컬렉션

namespace System.Collections{ public interface IEnumerable IEnumerator GetEnumerator(); }

GetEnumerator()라는 하나의 메서드를 포함, foreach 구문 등에서 개체를 하나씩 넘겨주는 역할을 한다.

이 메서드는 System.Collections.IEnumerator 인터페이스를 구현하는 Enumerator 개체를 돌려준다.

Enumerator 개체는 컬렉션의 요소들을 살펴보기 위해 사용된다.

Enumerator는 목록의 요소들을 가리키는 포인터라고 생각하자. 처음 포인터는 첫 번째 항목의 <앞부분>을 가리킨다.

(Enumerator가 가지는 state의 초깃값은 -1) MoveNext 메서드를 호출하면 현재 위치의 다음인 첫 번째 항목으로 이동한다.

메서드 호출 후 가리키는 항목이 존재하면 true를 반환하고 그렇지 않은 경우엔 false를 반환한다.

Current 속성은 현재 가리키는 항목에 접근할 때 사용하며, Reset 메서드는 목록에서 포인터가 첫 번째 항목의 앞부분을 재 지시하도록 설정해준다.

컬렉션의 GetEnumerator 메서드를 사용하여 Enumerator를 생성하고 MoveNext 메서드를 통해 반복 호출하여 

Enumerator 의 Current 속성 값을 읽어들이면 한 번에 하나씩 다음 컬렉션의 구성 요소들로 이동할 수 있다.

(이것은 foreach 구문과 기능적으로 동일하다.)

직접 나열 가능한 컬렉션 클래스를 새로 만들고자 한다면 컬렉션 클래스에서 IEnumerable 인터페이스와 IEnumerator 인터페이스를 함께 구현해야 한다.


foreach 문과 유사한 IEnumerator 기본 동작 예제


'Programming > C++, C#' 카테고리의 다른 글

[C#] Lambda Expression  (0) 2018.06.07
[C#] Generic  (0) 2018.06.06
[C#] Interface  (0) 2018.06.06
[C#] Delegate , Event  (0) 2018.06.06
[C#] Out vs Ref  (0) 2018.06.06

인터페이스는 상속받는 새로운 클래스가 기본 클래스로부터 함수를 구현해주는 약속이다.

메서드, 속성, 이벤트, 인덱서 또는 네가지 멤버 형식의 조합이 포함되며 구현 내용없이 서명만 정의한다.

제약 조건
  • 상수, 필드, 연산자, 인스턴스 생성자 소멸자 또는 형식이 포함될 수 없다.
  • 인터페이스(구현할 내용 지정)를 제외한 <구체적 구현 내용이 포함된>다른 어떠한 클래스로부터도 상속받지 않는다. 
즉 인터페이스에는 상속받을 클래스가 제공해야 하는 메서드와 속성들을 지정할 뿐이다.   
이것은 자식 클래스의 확장 가능한 프로그래밍 프레임 워크를 구성할 수 있는 좋은 방법을 제시해준다.

인터페이스 목적

다수의 프로그래머들이 참여하여 코드를 작성한다면 복잡성이 전반적으로 증가하게 될 것이다.

코드의 기본적인 일관성을 유지하기 위한 방편으로 이 점을 완화할 수 있다. (협업단계에서 필요)
-> 기본적인 구현 구조에 대한 방식을 통일, 그것을 시스템화하여 코드의 일관성과 안정성을 높일 수 있다.

인터페이스 구현

구현 클래스 또는 구조체의 해당 멤버가 공용이고 비정적이어야 하며 
인터페이스 멤버와 동일한 이름 및 서명을 사용하며 선언한 모든 항목에 대하여 구현부를 정의해야 한다.

'Programming > C++, C#' 카테고리의 다른 글

[C#] Generic  (0) 2018.06.06
[C#] IEnumerator  (0) 2018.06.06
[C#] Delegate , Event  (0) 2018.06.06
[C#] Out vs Ref  (0) 2018.06.06
[C#] Const vs Readonly  (0) 2018.06.06


델리게이트(delegate)

선언 형식delegate키워드 반환타입 델리게이트이름 (파라미터) delegate void delName(int input); 

쉽게 말해 메서드의 포인터 같은 개념이다. 참조할 수 있는 메서드의 형태를 정의하여 고유 식별자와 일치하는 메서드만 가리키도록 한다.

델리게이트가 지정하는 특정 타입의 인스턴스는 마치 추상 메서드를 정의하는 인터페이스의 역할과 닮아있다.

output

4 + 9 : 13

4 × 9 : 36

4 -9 : -5



이벤트(Event)

이벤트 멤버는 특정 타입으로 하여금 다른 객체에 뭔가 특별한 일이 발생했음을 알리는 용도로 사용한다.

즉 델리게이트 타입으로 선언을 하여 타입 안정성을 유지한 채로 콜백 메서드를 호출하기 위한 방법이다.

output

골드 : 10

골드 : 20

골드 : 30



'Programming > C++, C#' 카테고리의 다른 글

[C#] IEnumerator  (0) 2018.06.06
[C#] Interface  (0) 2018.06.06
[C#] Out vs Ref  (0) 2018.06.06
[C#] Const vs Readonly  (0) 2018.06.06
[C#] 박싱과 언박싱  (0) 2018.06.06


out 키워드

참조를 통해 메서드에 인수를 전달할 수 있다. (제한된 범위로 변수를 생성하는 경우 Out 키워드가 유용하다.)

output : 

37

큰 값: 37 작은 값: 13


Ref 키워드

ref는 참조로 전달되는 값을 나타낸다.

변수를 전달하기 전에 초기화해야 한다. (하나 이상의 함수에서 변수에 접근이 필요한 경우 유용)

output :

40


-> 메서드 시그니처 및 메서드 호출에서 인수를 메서드에 참조로 전달한다.

-> 메서드 시그니처에서 값을 호출자에게 참조로 반환한다.

-> 멤버 본문에서 참조 반환 값이 호출자가 수정하려는 참조로 로컬에 저장됨을 의미한다.
즉 인수를 참조로 전달하는 경우 호출된 메서드의 인수 변경 내용이 호출 메서드에 반영
메서드 매개 변수는 값 형식이든 참조 형식이든 관계없이 ref를 통해 수정할 수 있으며, 참조로 전달되는 경우 값 형식은 Boxing 되지 않는다

'Programming > C++, C#' 카테고리의 다른 글

[C#] Interface  (0) 2018.06.06
[C#] Delegate , Event  (0) 2018.06.06
[C#] Const vs Readonly  (0) 2018.06.06
[C#] 박싱과 언박싱  (0) 2018.06.06
[C#] 암시적 변환 vs 명시적 변환  (0) 2018.06.05

컴파일타임 상수 vs 런타임 상수 

변수와 달리 한번 정의해 둔 값으로서 더 이상 변경할 필요가 없는 것들을 의미한다.(ex 원주율)


Const  컴파일타임에 처리 (컴파일 타임에 변수가 값으로 대체된다)

    • 선언 시 반드시 그 값을 할당해야 한다. (변수를 정의할 때 초기화되고 그 이후로는 변경할 수 없다.)
    • Const는 내장된 숫자형, enum, 문자열, null에 대해서만 사용될 수 있다. (내장 자료형이어야만 컴파일 타임에 상수를 리터럴로 대체할 수 있기 때문)
    • Const 상수는 선언시 자동으로 Static 키워드가 추가된다

    Readonly - 런타임에 처리 (런타임에 값이 평가된다. 상수에 대한 참조로 컴파일 된다.)

      • 선언 시 반드시 값을 할당하지 않아도 된다.
      • Readonly는 모든 자료형에 대해 사용 가능하다.
      • Readonly는 변수 정의 이후에 생성자에서 한번 더 초기화 할 수 있으며 그 이후에는 수정 불가하다.

    Readonly 는 변수를 통해 값을 참조하기 때문에 Const보다 느리다.
    하지만 성능차이가 미미하기 때문에 대부분의 경우 유연성을 위해 Readonly를 사용하는 것이 좋다.


    'Programming > C++, C#' 카테고리의 다른 글

    [C#] Delegate , Event  (0) 2018.06.06
    [C#] Out vs Ref  (0) 2018.06.06
    [C#] 박싱과 언박싱  (0) 2018.06.06
    [C#] 암시적 변환 vs 명시적 변환  (0) 2018.06.05
    [C#] 값 타입 vs 참조 타입  (0) 2018.06.05


    인터페이스를 제외한 데이터 형식은 (특별한 타입이 정해져 있지 않은 참조 타입인) Object 타입으로부터 모두 파생된다.

    즉, 값 타입인 int 형도 더 큰 범주에 속해 있는 Object의 자식 객체라는 이야기가 된다.

    서로 다른 타입인 값 타입과 참조 타입은 Object 타입을 매개로 하여 박싱과 언박싱을 통해 서로에게 전달될 수 있다.


    박싱 : 값 타입 -> 참조 타입

    박스 내에 값 타입이 포함된다. 값 타입을 참조 타입으로 변경하기 위해 타입이 정해져 있지 않은(system.Objet) 익명의 참조 타입이 생성

    값 타입은 이 익명의 참조 타입 내부에 저장


    언박싱 : 값 타입 -> 참조 타입

    박싱되어 있는 참조 타입의 객체로부터 값 타입 객체의 복사본을 가져온다.

    "박싱과 언박싱은 System.Object 타입이나 인터페이스 타입이 필요한 곳에서 값 타입을 사용하기 위해 반드시 필요한 매커니즘이다.

    하지만 박싱과 언박싱은 성능에 좋지 않은 영향을 미친다. 때로는 박싱과 언박싱을 수행하는 과정에서 임시 객체가 생성되기도 하는데

    간혹 이로 인해 예상치 못한 버그가 발생하기도 한다. 따라서 박싱과 언박싱은 가능한 피하는 것이 좋다." 라고 -Effective C# 에서 설명함.

    'Programming > C++, C#' 카테고리의 다른 글

    [C#] Out vs Ref  (0) 2018.06.06
    [C#] Const vs Readonly  (0) 2018.06.06
    [C#] 암시적 변환 vs 명시적 변환  (0) 2018.06.05
    [C#] 값 타입 vs 참조 타입  (0) 2018.06.05
    클래스(정적멤버)  (0) 2018.06.05

    C#은 컴파일 시간에 정적으로 형식화되므로 변수가 선언된 이후 다시 선언되거나 다른 형식의 값을 저장하는 데 사용할 수 없다.


    (이말인즉슨 int 형을 string 형으로 변환할 수는 없다는 의미이다.)


    그러나 다른 형식의 변수 또는 메서드 매개 변수에 값을 복사해야 하는 경우도 있다.

    (예를 들어 매개 변수가 float 으로 형식화된 메서드에 int값을 가진 정수형 변수를 전달하는 경우)

     C#에서 형식 변환은 다음의 4가지 방법에 의해 수행된다.


    • 암시적 변환   
    • 명시적 변환   
    • 사용자 정의 변환 
    • 도우미 클래스를 사용한 변환


    암시적변환

    작은 범위에서 -> 큰 범위로 변환 / 파생클래스에서 -> 기본 클래스로 변환 (형식이 안전하고 데이터 손실 위험이 없다.)
    int-> float, gameObject -> object , transform -> component -> object (이런 경우 특수 구문이 필요하지 않다.)


    명시적변환

    큰 형(기본 클래스) -> 작은 형(파생 클래스)으로의 변환 (정보가 손실되거나 다른 이유로 변환이 실패할 수 있다.)

    그래서 cast란 것을 해야하는데 (cast : 컴파일러에서 (<Type>) 캐스트라는 특수구문을 거쳐 명시적 변환을 수행)

    이것은 변환을 수행하고자 할때 어떤 데이터의 손실 가능성을 짐작해 컴파일러에게 명시적으로 알리는 방법이다.


    컴파일러는 런타임에 객체가 어떤 타입일지 예측하지 못한다. 그래서 일부 참조 변환 시 컴파일러에서 캐스트가 유효한지 확인할 방법이 없는데 
    이경우에 오류메시지 없는 컴파일 단계의 캐스트 작업이 런타임에서는 실패를 유발할 수 있다.
    -> 따라서 실제 캐스트 수행 전 호환성을 테스트할 수 있는 is및 as 연산자를 사용해 안정성 여부를 확보해야 한다.


    다음과 같은 상속관계에 있는 클래스 구도에서의 is 및 as 연산자를 사용하는 경우를 살펴보자


    이처럼 is 연산자는 보안성을 입증하는데 문제없지만  객체의 실제 타입을 파악하기 위해 상속관계를 탐색하며 각 타입을 조사해야 한다. 

    이것은 성능에 관한 비용을 발생시키므로  -> (성능 개선의 이유로) as 연산자를 사용할 것을 (effective c#) 책에서 권고하고 있다.


    'Programming > C++, C#' 카테고리의 다른 글

    [C#] Const vs Readonly  (0) 2018.06.06
    [C#] 박싱과 언박싱  (0) 2018.06.06
    [C#] 값 타입 vs 참조 타입  (0) 2018.06.05
    클래스(정적멤버)  (0) 2018.06.05
    클래스(생성자)  (0) 2018.06.04


    Value type

    primitive Type(int, float, bool, char 와 같은 기본 데이터 타입)과 구조체가 이에 해당한다.

    변수의 선언과 동시에 값을 할당할 수 있으며 스텍에 메모리가 생성된다. 이렇게 단일한 공간에 

    생선된 데이터는 직접적이며 변수의 대입이나 매개변수로 데이타를 전달할 때 메모리 복사가 일어난다.


    Reference type

    Class, String, Object (이것들과 더불어 배열은 그 구성요소의 형식과 상관없이 항상 참조 형식이다.)

    참조 타입을 사용하기 위해선 new 키워드를 통해 객체를 초기화한 후 힙에 할당된 메모리를 스택공간에서 참조해야 한다. 

    객체를 지시하는 메모리는 필요로하는 메모리공간(힙)의 주소와 그것을 가리키는 참조 값(스택)으로 분리되어 저장된다.

    다시말해 아직 수행되지 않은 데이터를 위해 예약어인 new 키워드를 사용해 객체를 초기화하여 인스턴스를 만들면 

    그 과정에서 시스템은 힙공간에 필요한 만큼의 메모리 블록을 준비하여 스택에서 그 주소 정보를 참조할 수 있도록 해준다. 

    여기서 참조 타입의 변수를 다른 곳에 대입하거나 매개변수로 데이터를 전달 할 때도 reference 자체만 복사되고 

    실제 참조로 가리키는 힙에 저장된 메모리는 동일하다.


    참조 변수로 객체 참조하기


    참조 변수인 trollPick 과 normalPick 은 객체의 주소값을 의미하고 스택에 저장된다. 그리고 이들이 가리키는 메모리 공간의 실제 대상인 객체가 힙에 저장된다. 

    여기서 trollPick 참조 변수에 normalPick 참조 변수를 대입한다면


    ->말로 다시 풀이해보자면 타릭이라는 기존의 normalPick이 trollPick이라는 새로운 별칭을 얻었고 
    그동안 trollPick의 대명사로 불렸던 마스터 이는 이제 어떤 참조로도 형용할 방법이 없어진 것과 같다.
    이렇게 객체 정보를 어떤 변수에서도 참조하지 않게 되면 시스템에서는 그 객체를 가비지 컬렉(Garbagecollection)의 대상으로 표시하게 되고
    더 이상 참조되지 않는 객체는 제거되며 그 객체가 점유하고 있던 메모리 공간을 회수해간다.
    그런데 이 Garbage collection은 상당히 비용이 큰 연산이기 때문에 특별한 경우를 제외하고 최대한 이런 작업은 줄이도록 노력해야 한다.


    프로그램의 어딘가에서 참조변수가 다른 객체를 참조하도록 예정되어 있다면 다음과 같이 코드를 수정하는 것이 좋다.


    'Programming > C++, C#' 카테고리의 다른 글

    [C#] 박싱과 언박싱  (0) 2018.06.06
    [C#] 암시적 변환 vs 명시적 변환  (0) 2018.06.05
    클래스(정적멤버)  (0) 2018.06.05
    클래스(생성자)  (0) 2018.06.04
    클래스(캡슐화)  (0) 2018.06.04

    + Recent posts