MerlinVR / UdonSharp

An experimental compiler for compiling C# to Udon assembly
MIT License
678 stars 89 forks source link

null string is conveted into empty string when accessing from other class #32

Closed naqtn closed 4 years ago

naqtn commented 4 years ago

Describe the bug in detail: Prepare two U# class. Let the one has a string variable with null value. When the another class access the variable the value becomes empty string.

Provide steps/code to reproduce the bug: Referenced class:

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class OtherClassNullStringBecomesEmpty_Sub : UdonSharpBehaviour
{
    public string foo;

    void Start()
    {
        foo = null;
    }

    void Interact()
    {
        string s = foo;
        Debug.Log("Sub: eqNull=" + (s == null) + " isEmpty=" + string.Empty.Equals(s));
    }
}

Refering class:

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class OtherClassNullStringBecomesEmpty : UdonSharpBehaviour
{
    public OtherClassNullStringBecomesEmpty_Sub other;

    void Interact()
    {
        string s = other.foo;
        Debug.Log("Main: eqNull=" + (s == null) + " isEmpty=" + string.Empty.Equals(s));

        object o = other.foo;
        Debug.Log(" obj: eqNull=" + (o == null) + " isEmpty=" + string.Empty.Equals(o));
    }
}

Expected behavior: Actual result:

    Main: eqNull=False isEmpty=True
     obj: eqNull=False isEmpty=True

I expected: eqNull=True isEmpty=False at least "object o" case.

For comparing, the result of accessing from declaring class:

Sub: eqNull=True isEmpty=False

It is surely that the variable value is null in referenced class.

Additional Information: Generated assembly of accessing part:

         # string s = other.foo;
        PUSH, other
        PUSH, __0_const_intnl_SystemString
        PUSH, __0_intnl_SystemObject
        EXTERN, "VRCUdonCommonInterfacesIUdonEventReceiver.__GetProgramVariable__SystemString__SystemObject"
        PUSH, __0_intnl_SystemObject
        PUSH, __0_s_String
        EXTERN, "SystemConvert.__ToString__SystemObject__SystemString"
         # object o = other.foo;
        PUSH, other
        PUSH, __0_const_intnl_SystemString
        PUSH, __0_o_Object
        EXTERN, "VRCUdonCommonInterfacesIUdonEventReceiver.__GetProgramVariable__SystemString__SystemObject"
        PUSH, __0_o_Object
        PUSH, __7_intnl_SystemString
        EXTERN, "SystemConvert.__ToString__SystemObject__SystemString"
        PUSH, __7_intnl_SystemString
        PUSH, __0_o_Object
        COPY

It uses Convert.ToString(Object). The API reference of that: https://docs.microsoft.com/en-us/dotnet/api/system.convert.tostring?view=netframework-4.0#System_Convert_ToString_System_Object_

The document says the return value is

or Empty if value is null.

So, the issue happens.

MerlinVR commented 4 years ago

Resolved in 0.17.0