반응형
형변환 이란?
하나의 데이터 타입을 다른 데이터 타입으로 변환하는 것
형변환의 종류
암시적 형변환 ( 자동 형변환 )
int num = 10;
float floatNum = num; // int → float 자동 변환
long longNum = num; // int → long 자동 변환
사용 시기
- 작은 크기의 데이터 타입에서 큰 크기로 변환할 때
- 데이터 손실의 위험이 없어 자동으로 변환됨
명시적 형 변환 ( 강제 형변환 )
float floatNum = 10.5f;
int num = (int)floatNum; // float → int 강제 변환
// 10이 저장됨 (소수점 이하 손실)
사용시기
- 큰 크기의 데이터 타입에서 작은 크기로 변환할 때
- 데이터 손실의 가능성이 있어 명시적으로 변환해야 함
사용 예시
기본 데이터 타입 변환
public class PlayerController : MonoBehaviour
{
private float speed = 5.5f;
void Update()
{
// float을 int로 변환 (체력 계산 등에 사용)
int roundedSpeed = (int)speed; // 5가 됨
// int를 float으로 변환 (부드러운 움직임 계산 등에 사용)
int score = 100;
float smoothScore = score; // 자동 변환
}
}
게임오브젝트와 컴포넌트 변환
public class Enemy : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
// GameObject를 Player 타입으로 변환 시도
Player player = other.gameObject.GetComponent<MonoBehaviour>() as Player;
if(player != null)
{
player.TakeDamage(10);
}
}
}
주의사항
1. 데이터 손실 가능성
float health = 95.7f;
int roundedHealth = (int)health; // 95가 됨 (소수점 손실)
2. 변환 실패 가능성
public void HandleObject(GameObject obj)
{
// 잘못된 방법 (예외 발생 가능)
Player player = (Player)obj;
// 안전한 방법
Player safePlayer = obj as Player;
if(safePlayer != null)
{
// 변환 성공
}
}
3. 성능 고려
void Update()
{
// 나쁜 예 - 매 프레임마다 형변환
for(int i = 0; i < 1000; i++)
{
float value = (float)i;
// 처리...
}
// 좋은 예 - 필요한 경우에만 형변환
float convertedValue = (float)someInteger;
for(int i = 0; i < 1000; i++)
{
// convertedValue 사용
}
}
C# 형변환의 다양한 방법
1. typeof 연산자
타입의 정보를 얻는 연산자
Type t = typeof(string);
Debug.Log(t.Name); // "String" 출력
간단예제 및 주의사항
public class Weapon : MonoBehaviour { }
public class Sword : Weapon { }
public class Bow : Weapon { }
public class WeaponManager : MonoBehaviour
{
void CheckWeapon(Weapon weapon)
{
// 문제가 되는 상황
if(weapon.GetType() == typeof(Weapon))
{
// Sword나 Bow는 여기서 false가 됨
// 실제로는 무기지만 정확한 타입이 다르기 때문
}
// 더 나은 방법들
// 1. IsSubclassOf 사용
if(weapon.GetType().IsSubclassOf(typeof(Weapon)))
{
Debug.Log("이것은 무기의 파생 클래스입니다.");
}
// 2. is 연산자 사용
if(weapon is Weapon)
{
Debug.Log("이것은 무기입니다. (파생 클래스도 포함)");
}
}
}
2.GetType() 메서드
객체의 실제 타입을 얻는 메서드
string str = "Hello";
Type type = str.GetType();
Debug.Log(type.Name); // "String" 출력
간단예제 및 주의사항
public class ItemSystem : MonoBehaviour
{
void ProcessItem(Item item)
{
// 문제가 되는 상황
Type itemType = item.GetType(); // item이 null이면 NullReferenceException 발생
// 안전한 방법
if(item != null)
{
Type itemType = item.GetType();
Debug.Log($"아이템 타입: {itemType.Name}");
}
else
{
Debug.LogWarning("아이템이 null입니다!");
}
}
}
3. is와 as 연산자
is: 타입 검사
as: 안전한 타입 변환
object obj = "Hello";
if(obj is string) // 타입 검사
{
string str = obj as string; // 안전한 변환
}
is 간단예제 및 주의사항
public class Enemy : MonoBehaviour { }
public class Boss : Enemy { }
public class MinionBoss : Boss { }
public class EnemyManager : MonoBehaviour
{
void HandleEnemy(GameObject obj)
{
var component = obj.GetComponent<MonoBehaviour>();
// is의 특징: 상속 관계의 모든 객체를 확인
if(component is Enemy) // Enemy, Boss, MinionBoss 모두 true
{
Debug.Log("적입니다!");
}
// 패턴 매칭을 사용한 더 유용한 방법
if(component is Boss boss)
{
// boss 변수를 바로 사용 가능
boss.TriggerBossPhase();
}
}
}
as 간단예제 및 주의사항
public class InteractionSystem : MonoBehaviour
{
void HandleInteraction(MonoBehaviour component)
{
// 값 형식에는 사용 불가
// int number = obj as int; // 컴파일 에러!
// 참조 형식에만 사용 가능
var enemy = component as Enemy;
// as 연산자의 장점: 형변환 실패시 예외 대신 null 반환
if(enemy != null)
{
enemy.Attack();
}
else
{
Debug.Log("Enemy가 아닙니다.");
}
// 캐스팅과의 비교
try
{
Enemy forcedEnemy = (Enemy)component; // 실패시 예외 발생
}
catch(InvalidCastException)
{
Debug.LogError("형변환 실패!");
}
}
}
4. 직접 캐스팅 ( Type Casting )
명시적 형변환 연산자
double d = 3.14;
int i = (int)d; // 명시적 형변환
간단예제 및 주의사항
public class DamageSystem : MonoBehaviour
{
void CalculateDamage()
{
// 1. 데이터 손실
float damage = 15.7f;
int roundedDamage = (int)damage; // 15가 됨 (0.7 손실)
// 2. OverflowException 가능성
long bigNumber = long.MaxValue;
int smallNumber = (int)bigNumber; // OverflowException 발생
// 3. InvalidCastException 가능성
GameObject obj = new GameObject();
try
{
Enemy enemy = (Enemy)obj.GetComponent<MonoBehaviour>();
// MonoBehaviour가 Enemy가 아니면 예외 발생
}
catch(InvalidCastException)
{
Debug.LogError("Enemy로 변환 실패!");
}
}
}
5. Convert 클래스
다양한 타입 변환 메서드 제공
string numberString = "123";
int number = Convert.ToInt32(numberString);
간단예제 및 주의사항
public class DataConverter : MonoBehaviour
{
void ConvertData(string input)
{
try
{
// FormatException: 잘못된 형식
int number = Convert.ToInt32("abc"); // 실패
// OverflowException: 값 범위 초과
int tooLarge = Convert.ToInt32("999999999999"); // 실패
// ArgumentNullException: null 입력
float value = Convert.ToSingle(null); // 실패
}
catch(FormatException)
{
Debug.LogError("잘못된 형식입니다.");
}
catch(OverflowException)
{
Debug.LogError("값이 범위를 벗어났습니다.");
}
catch(ArgumentNullException)
{
Debug.LogError("null은 변환할 수 없습니다.");
}
}
}
6. Parse 메서드
문자열을 다른 타입으로 변환
string numStr = "456";
int num = int.Parse(numStr);
7.TryParse 메서드
안전한 형식 변환 시도
string input = "789";
if(int.TryParse(input, out int result))
{
Debug.Log("변환 성공: " + result);
}
간단예제 및 주의사항 ( Parse와 Tryparse의 차이 )
public class ScoreSystem : MonoBehaviour
{
void ProcessScore(string scoreText)
{
// Parse: 실패시 예외 발생
try
{
int score = int.Parse(scoreText);
UpdateScore(score);
}
catch(FormatException)
{
Debug.LogError("점수 형식이 잘못되었습니다.");
}
// TryParse: 안전한 방식
if(int.TryParse(scoreText, out int parsedScore))
{
UpdateScore(parsedScore);
}
else
{
Debug.LogWarning("점수를 변환할 수 없습니다.");
}
}
private void UpdateScore(int score)
{
// 점수 업데이트 로직
}
}
반응형
'유니티 > 문법' 카테고리의 다른 글
[Unity] 유니티 C#) Property ( 프로퍼티 ) (0) | 2025.01.20 |
---|---|
[Unity] 유니티C#) Struct ( 구조체 ) (1) | 2025.01.17 |
[Unity] 유니티 C#) try-catch문 ( 예외처리 ) (1) | 2025.01.15 |
[Unity] 유니티 C#) LINQ ( Language Integrated Query ) (1) | 2025.01.14 |
[Unity] 유니티 C#) 전처리문 (Preprocessor Directives) (0) | 2025.01.13 |