1. UnityEngine.Object == null
๊ฐ๋ฐ ์ ๊ฐ์ฒด๊ฐ ์ค์ ๋ก ์กด์ฌํ๋์ง ํ์ธํ๊ธฐ ์ํด == null ์ฒดํฌ๋ฅผ ์์ฃผ ์ฌ์ฉํ๊ณค ํ๋ค. ๊ณผ์ฐ ์ด ๋ฐฉ๋ฒ์ด ์ต์ ์ผ๊น?
2. fake null
"UnityEngine.Object == null์์์ null์ด ์ง์ง null์ด ์๋๋ค! ์ฆ, fake null์ด๋ค"๋ผ๋ ๋ง์ด ์กด์ฌํ๋ค. ์ ๊ทธ๋ด๊น?
์์ธ์ ์ ๋ํฐ์์์ null๊ณผ System์์์ null์ ์ฐจ์ด์ด๋ค. ์ด ์ฐจ์ด๋ฅผ ์์๋ณด๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด, UnityEngine.Object์ System.Object์ null ์ฒดํฌ ๊ฐ์ด ๋ค๋ฅธ ๊ฒ์ ํ์ธํ ์ ์๋ค.
var obj = new GameObject();
yield return null;
Destroy(obj);
yield return null;
print($".Net Object : {(obj as System.Object) == null}");
print($"Unity Object : {(obj as UnityEngine.Object) == null}");
//๊ฒฐ๊ณผ
//.Net Object : False
//Unity Object : True
UnityEngine.Object ํด๋์ค๋ ์ ๋ํฐ์์ ์์ฑํ nativeObject ๊ฐ์ฒด์ ๋ํ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ Wrapping ํด๋์ค์ด๋ค. ์ ๋ํฐ๋ ์ค์ ๋ก๋ C++๋ก ๊ตฌํ๋์ด ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์กด์ฌํ์ง ์์ nativeObject ๊ฐ์ฒด์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ํด์ ํด์ผ ํ๋ค. ๊ทธ๋ฌ๋ UnityEngine.Object๋ C#์ผ๋ก ๊ตฌํ๋์ด ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ์๋์ผ๋ก ํด์ ํ๋ค.
- C++ nativeObject: ์ฆ์ ๋ฉ๋ชจ๋ฆฌ ํด์
- C# UnityEngine.Object: ์ฆ์ ๋ฉ๋ชจ๋ฆฌ ํด์ ๋์ง ์๊ณ ๊ฐ๋น์ง ์ฝ๋ ํฐ์ ์ํด ํด์
์ฆ, ์๋งน์ด(C++ NativeObject)๋ง ์ฌ๋ผ์ง๊ณ ๊ป๋ฐ๊ธฐ(UnityEngine.Object)๋ ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ์ฒ๋ฆฌํด ์ค ๋๊น์ง ๊ณ์ ๋ฉ๋ชจ๋ฆฌ ์์ ์กด์ฌํ๋ ๊ฒ์ด๋ค.
3. ๋น๊ต ์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ
Rider IDE์์ fake null๋ก null ์ฒดํฌ๋ฅผ ํ๋ฉด ๋ค์๊ฐ ๊ฐ์ ์๋ด๊ฐ ๋์จ๋ค. ๋จ์ํ null ์ฒดํฌ์ธ ์ค ์์๋๋ฐ, ์ ๋น์ฉ์ด ํด๊น?
UnityEngine.Object์ ==, != ์ฐ์ฐ์๋ ๋น๊ต ์ฐ์ฐ์๋ฅผ ์ค๋ฒ๋ก๋ฉํ ๊ฒ์ผ๋ก ์ค์ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด ๋ง์ ๊ฒ์ ์ํํ๋ ๊ฒ์ ์ ์ ์๋ค.
- object ํ์ ์ผ๋ก ๋ค์ด์บ์คํ ํ null ๋น๊ต ์งํ
- lhs ํน์ rhs๊ฐ null์ด ์๋ ๊ฒฝ์ฐ IsNativeObjectAlive() ํจ์๋ฅผ ํธ์ถํ์ฌ ์ค์ ๊ฐ์ฒด๊ฐ ์์ง ์ ํจํ์ง ๊ฒ์ฌ
- IsNativeObjectAlive() ํจ์
- ํฌ์ธํฐ ๊ฐ์ด ์ ํจํ์ง ๊ฒ์ฌ
- MonoBehaviour ํ์ ์ด๊ฑฐ๋ ScriptableObject ํ์ ์ผ ๊ฒฝ์ฐ์ ์์ ๊ฒ์ฌํ์ง ์๊ณ False ๋ฆฌํด
- InstanceID๊ฐ ๋์ผํ ์ค๋ธ์ ํธ์ธ์ง ๊ฒ์ฌ
// UnityEngine.Object
public static bool operator==(Object x, Object y) { return CompareBaseObjects(x, y); }
public static bool operator!=(Object x, Object y) { return !CompareBaseObjects(x, y); }
static bool CompareBaseObjects(UnityEngine.Object lhs, UnityEngine.Object rhs)
{
bool lhsNull = ((object)lhs) == null;
bool rhsNull = ((object)rhs) == null;
if (rhsNull && lhsNull) return true;
if (rhsNull) return !IsNativeObjectAlive(lhs);
if (lhsNull) return !IsNativeObjectAlive(rhs);
return lhs.m_InstanceID == rhs.m_InstanceID;
}
static bool IsNativeObjectAlive(UnityEngine.Object o)
{
if (o.GetCachedPtr() != IntPtr.Zero)
return true;
if (o is MonoBehaviour || o is ScriptableObject)
return false;
return DoesObjectWithInstanceIDExist(o.GetInstanceID());
}
[NativeMethod(Name = "UnityEngineObjectBindings::DoesObjectWithInstanceIDExist", IsFreeFunction = true, IsThreadSafe = true)]
internal extern static bool DoesObjectWithInstanceIDExist(int instanceID);
3. ๊ฐ์
1) is null (C# 7.0)
object[] data = { 1, null, 10, new Circle(5), new Person("Lee"), "" };
foreach (var item in data)
{
if (item is null)
{
Console.WriteLine("NULL ์ฐพ์์");
}
}
2023.01.14 - [๐ Language/โ C#] - [C# 7.0] ์๋ก์ด ๊ธฐ๋ฅ (1) - ํจํด ๋งค์นญ
2) ReferenceEquals
object[] data = { 1, null, 10, new Circle(5), new Person("Lee"), "" };
foreach (var item in data)
{
if (ReferenceEquals(item, null))
{
Console.WriteLine("NULL ์ฐพ์์");
}
}
์ฐธ๊ณ
https://doublsb.tistory.com/138