▶인덱서란?
C++의 인덱스 연산자 오버로딩과 같이 객체의 인덱스 연산을 시킬 때 특정함수를 호출해주는 메커니즘을 의미한다.
즉, 객체를 배열처럼 사용하는 것이 가능하다.
- 가독성 + 중복 로직 방지
▷ C# 인덱서의 특징
-C# 언어의 인덱서는 this 키워드와 인덱스 연산자 ( [] )를 조합해서 정의하는 것이 가능하다.
-C#언어의 인덱서는 this 키워드를 통해서 정의되기 때문에 정적 클래스는 인덱서를 정의하는 것이 불가능하다.
-C# 언어의 인덱서는 프로퍼티와 마찬가지로 get과 set을 통해서 로직을 정의하는 것이 가능하다.
-C# 언어의 인덱서는 메서드와 마찬가지로 virtual 과 override 키워드의 조합으로 오버라이드 매커니즘을 구현하는 것이 가능하다.
▶제네릭이란?
C++의 템플릿과 마찬가지로 클래스 또는 메서드를 정의할 때 타입을 지정하지 않고 구현할 수 있는 매커니즘을 의미한다.
▷ 제네릭의 특징
- C#언어의 제네릭은 <T>와 같은 제네릭 타입을 명시함으로써 정의하는 것이 가능하다.
(ex) Class CWidget<T>
- C# 언어의 제네릭은 기본적으로 모든 데이터 타입에 동작하도록 설계되어야 한다.
- 제네릭 클래스 또는 메서드에 어떤 데이터 타입이 지정되어도 내부 로직에 변화가 발생하면 안된다.
(설계를 할 때 컴파일 오류(빨간줄) /논리오류 를 고려해야한다.)
▷ C# 언어 제네릭의 데이터 타입 제한
- class CWidget<T> where T : class (타입을 참조 형식으로 제한)
- class CWidget<T> where T : struct (타입을 값 형식으로 제한)
- class CWidget<T> where T : SomeClass (타입을 SomeClass를 직/ 간접적으로 상속하는 형식으로 제한)
- class CWidget<T> where T : SomeInterface (타입을 SomeInterface 직/ 간접적으로 따르는 형식으로 제한)
- class CWidget<T, U> where T : U (타입을 U(클래스 or 인터페이스)를 직/간접적으로 상속하는 형식으로 제한)
위의 인덱서 예시를 제네릭화했을 때.
▷ is 와 as 연산자를 통한 데이터 형변환
is 연산자 : 결과 값이 참/ 거짓으로 판정되며 값 형식과 참조 형식 데이터에 모두 사용하는 것이 가능하다.
as 연산자 : 결과를 해당 데이터 형의 참조 값으로 반환시키기 때문에 참조 형식의 데이터 타입에만 사용하는 것이 가능하다.
(ex)
is 연산자
object oIntObject = 10;
if(oIntObject is int)
{
//
}
as 연산자
object oClassObject = new someClass();
var SomeClass = oClassObject as SomeClass;
if(oSomeClass !=null)
{
//
}
▶확장메서드란?
기존에 제공되는 클래스 또는 외부 라이브러리에 속해있는 클래스에
새로운 기능을 "상속"이 아닌 메서드를 이용해서 기능을 확장하는 것을 의미
▷확장메서드의 특징
- c#언어의 확장 메서드는 정적 클래스만을 통해서 정의하는 것이 가능하다.
즉, 정적 클래스가 아니면 확장 메서드 자체를 구현하는 것이 불가능하다.
- c#언어의 확장 메서드를 정의하는 정적 클래스는 반드시 최상단 영역에 위치 시켜야한다.
- 특정 클래스의 중첩 클래스로는 확장 메서드를 정의하는 것이 불가능
(참고)
- 참고로 C#은 상속 하나만 가능. (다중상속 x ) + 확장메서드 + 인터페이스
- 확장 메서드에는 함수의 집합 또는 메서드의 집합이 들어가는게 베스트
- 코드의 간결화, 불필요한 로직제거, 중복 로직 제거
확장메서드 예시)
static class CArrayExtends
{
//! 값을 교환한다.
public static void Swap(this int[] a_oSender, int a_nLhs, int a_nRhs)
{
int nTemp = a_oSender[a_nLhs];
a_oSender[a_nLhs] = a_oSender[a_nRhs];
a_oSender[a_nRhs] = nTemp;
}
//!문자열을 반환한다.
public static string GetString(this int[] a_oSender)
{
var oStringBuilder = new System.Text.StringBuilder();
for(int i=0;i<a_oSender.Length;i++)
{
oStringBuilder.AppendFormat("{0}, ", a_oSender[i]);
}
return oStringBuilder.ToString();
}
//!합계를 계산한다.
public static int GetSumValue(this int[] a_oSender , int a_nDefaultValue = 0)
{
int nSumValue = a_nDefaultValue;
for(int i =0;i<a_oSender.Length; i++)
{
nSumValue += a_oSender[i];
}
Debug.Log("GetSumValue 호출");
return nSumValue;
}
//!합계를 계산한다. - 제네릭 버전
//Example_03.CArrayList는 위의 제네릭 예시 확장메서드. (Example_03은 스크립트네임)
public static object GetSumValue<T> (this Example_03.CArrayList<T> a_nSender) where T : struct
{
//제네릭 타입을 통해서 메서드 or 함수를 만들 때는 반드시 예외를 걸어줘야한다.(조건문 등으로)
object oSumValue = 0;
for(int i=0;i<5;i++)
{
int nValue = 0;
string oString = a_nSender[i].ToString();
if(int.TryParse(oString, out nValue)) //예외처리
{
oSumValue = (int)oSumValue + nValue;
}
}
return oSumValue;
}
//!평균을 계산한다.
public static float GetAverageValue(this int[] a_oSender)
{
Debug.Log("GetAverageValue 호출");
return GetSumValue(a_oSender) / (float)a_oSender.Length; //(float) : 혹시 모를 데이터 손실을 위해
}
}
외부 클래스에서 이 확장메서드를 참고하는 경우
(참고)
캐스팅(형변환) 연산자
C : (Type) =강제형변환 (좋은 방식은 아님, 오류 발생 가능성 높음)
C++
C# : 대표적인 형변환 3총사(Convert, Parse, TryParse)
<C# 캐스팅 연산자>
Convert
- '기본' 데이터 형식을 다른 '기본' 데이터 형식으로 변환
(기본데이터 형식 : int, byte, char, bool 등..)
parse
- 문자열을 해당하는 형식으로 변환시킨다.
TryParse
- 문자열을 해당하는 형식으로 변환시키면 성공 여부 T/F
-체크해야할 String 값이 숫자인 경우
: int 타입으로 컨버팅해서 반환
-체크해야할 String 값이 숫자가 아닌 경우
: 설정한 기본값으로 변환
'C# > C# 학습 (TIL)' 카테고리의 다른 글
유니티 safe Area 대응 (1) | 2022.12.12 |
---|---|
C# SendMessage / Attributes (0) | 2022.07.02 |
C# 컬렉션 - 딕셔너리 / 해쉬테이블 (0) | 2022.06.30 |
C# Array 배열/ Static Class 정적 클래스 / Extend Method 확장메서드 / 변수 표기법 / StringBuilder (0) | 2022.06.29 |
C# 자료형의 특징 , 변수의 특징 - 값 형식 / 참조 형식 데이터 타입 (0) | 2022.06.29 |