5 ms·
In case some JavaScript developers are looking for Wats in other languages when people come to beat up on JS again :), here's a "delightful" one from Unity in C
by johnfn 4y ago
In case some JavaScript developers are looking for Wats in other languages when people come to beat up on JS again :), here's a "delightful" one from Unity in C# that I've had in my notes for years but never published anywhere. (Note that C# by itself doesn't have this behavior of course - Unity is the Wat factory.)
[Serializable]
public class Foo {
public String bar = "Wat";
}
public class Test: MonoBehaviour {
public Foo foo = null;
void Update() {
Debug.Log(foo.bar); // logs Wat
}
}
- cheeze 4y agoYou can do the same with statics in Java
- kelnos 4y agoNot with that syntax. That syntax declares 'bar' as an instance variable. and 'foo' there is a null pointer, so trying to dereference it like that should produce a NullPointerException. Sure, you could change the declaration of 'bar' to include 'static', and change the access of 'bar' from 'foo.bar' to 'Foo.bar', but... that's not what the code says.
- twic 4y agoI think you can do the same in C++, or at least something very similar. If a method isn't virtual and doesn't touch the object's fields, you can invoke it on null quite happily. Doesn't Go do this too?
- extrememacaroni 4y agoThis should not happen if you use Odin and its serializer, a dropdown allowing you to create a new instance of type Foo will show up in the editor.
- capableweb 4y agoDoes Odin come by default with Unity? If not, I'm confident a lot more people don't have it, than those that do.
- doesnt_know 4y agoAs someone who writes (not Unity) C# for a living, what is going on here? Does Unity maintain it's own, non-standard version of C# and it changed the behavior of null?
- squeaky-clean 4y agoThe short version from the Unity docs "Inline serialization can’t represent null, instead, it replaces null with an inline object that has unassigned fields."[0] The key thing here is the [Serializable] attribute above the class. [Serializable] is an attribute provided by the Unity Engine. It's used to convert in-memory data structures / objects into a format that can be stored and loaded easily. You could use it to build a save system for your game, but more generally it's used for working on your project in the Unity Editor and then savings those to .scene, .prefab, .asset files and so on. Serializable objects and their fields (public fields are serialized by default) are editable in Unity Editor's Inspector tab, which is great for quickly iterating and working with designers who don't want to open a code editor or Excel in order to modify game object values and scenes. But Serializable has some "wat" moments and one of them is that it does not support null objects. MonoBehaviour is a Serializable type provided by UnityEngine. You generally make Game Objects by composing together different MonoBehaviours. Because the "Test" Monobehaviour has a public field"Foo foo", it is serialized by default. But it cannot be null. If it is assigned to null, Unity replaces it with an instance that has default field values. The correct way to handle this (though not very obvious unless you're deep into Unity) is to use the [SerializableReference] attribute instead. Or even better, follow extrememacaroni's recommendation to use Odin's serializer replacement. It's Apache license and basically a drop-in replacement with some additional features. No non-standard C# involved here, just the runtime reflection allowed by attributes. [0] https://docs.unity3d.com/Manual/script-Serialization.html https://docs.unity3d.com/Manual/script-Serialization.html
- kevingadd 4y agoUnity does in fact have a special approach to nullability, though they may have recently changed it. They (iirc, it's been a while) overloaded the == and != operators so that non-null instances could compare equal to null if the native object represented by the C# object had been destroyed.