C# 에서는 클래스나 구조체에서 연산자의 동작을 재정의할 수 있다.
Unity 에서 흔히 사용하는 Vector3 의 +,- 도 operator 를 사용하였다.
public struct Vector3
{
public float x,y,z;
public Vector3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public static Vector3 operator +(Vector3 a, Vector3 b)
{
return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
}
}
유니티의 Vector3 구현부에서 찾아볼 수 있었다.
스탯 클래스 간에 + 연산을 하여 더 높은 스탯을 반환하는 연산자로 예를 들어보았다.
public class Stats
{
public readonly int Hp;
public readonly int Mp;
public Stats(int hp, int mp)
{
Hp = hp;
Mp = mp;
}
public static Stats operator + (Stats a, Stats b)
{
return new Stats(a.Hp + b.Hp, a.Mp + b.Mp);
}
}
static void Main(string[] args)
{
Stats magician = new Stats(500, 400);
Stats warrior = new Stats(1000, 100);
Console.WriteLine($"magician's HP : {magician.Hp}, MP : {magician.Mp}");
Console.WriteLine($"warrior's HP : {warrior.Hp}, MP : {warrior.Mp}\n");
Stats magic_warrior = magician + warrior;
Console.WriteLine($"magic_warrior's HP : {magic_warrior.Hp}, MP : {magic_warrior.Mp}");
}
개발자가 의도를 명확히 표시해야 하는 변환 (명시적 변환)
Stats → int 로 명시적 변환하여
Stats 을 Hp 와 Mp 의 합인 int 으로 반환하도록 한다.
internal class Program
{
public class Stats
{
public readonly int Hp;
public readonly int Mp;
public Stats(int hp, int mp)
{
Hp = hp;
Mp = mp;
}
public static Stats operator +(Stats a, Stats b)
{
return new Stats(a.Hp + b.Hp, a.Mp + b.Mp);
}
public static explicit operator int(Stats a)
{
return a.Hp + a.Mp;
}
}
static void Main(string[] args)
{
Stats magician = new Stats(500, 400);
Stats warrior = new Stats(1000, 100);
Console.WriteLine($"magician's HP : {magician.Hp}, MP : {magician.Mp}");
Console.WriteLine($"warrior's HP : {warrior.Hp}, MP : {warrior.Mp}\n");
Stats magic_warrior = magician + warrior;
Console.WriteLine($"magic_warrior's HP : {magic_warrior.Hp}, MP : {magic_warrior.Mp}");
int stats_value = (int) magic_warrior; // (int) 가 빠지면 오류
Console.WriteLine($"magic_wariior's power : {stats_value}");
}
}
자동 변환을 허용 (암시적 변환)
int → Stats 로 암시적 변환으로 캐스팅 없이 자동 변환이 가능하다.
Hp 에만 값을 넣고, Mp 에는 0 을 넣어준다.
internal class Program
{
public class Stats
{
public readonly int Hp;
public readonly int Mp;
public Stats(int hp, int mp)
{
Hp = hp;
Mp = mp;
}
public static Stats operator +(Stats a, Stats b)
{
return new Stats(a.Hp + b.Hp, a.Mp + b.Mp);
}
public static explicit operator int(Stats a)
{
return a.Hp + a.Mp;
}
public static implicit operator Stats(int value)
{
return new Stats(value, 0);
}
}
static void Main(string[] args)
{
Stats tanker = 2000;
Console.WriteLine($"tanker's HP : {tanker.Hp}, MP : {tanker.Mp}");
Console.WriteLine($"tanker's power : {(int)tanker}");
}
}
객체를 수학적/직관적으로 다루고 싶다면 operator 를 활용하여
코드의 가독성, 직관성을 높여보자.
변환 과정에서 데이터 손실 가능성이 있어 개발자 의도를 명확히 표현하게 하고 싶다면
explicit operator 명시적 변환을,
안전한 변환을 자연스럽게 자동화 하고 싶다면
implicit operator 암시적 변환을 사용해보자.