Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question InvalidProgramException: Invalid IL code

Discussion in 'Editor & General Support' started by RoughDiamond, May 4, 2021.

  1. RoughDiamond

    RoughDiamond

    Joined:
    Dec 14, 2019
    Posts:
    12
    So I'm getting an InvalidProgramException on the following code snippets. Basically, I have a class
    Descriptor
    and a derived class
    Descriptor_Number
    , and I can't seem to call the method in the
    Descriptor_Number
    from a MonoBehaviour.

    I tried several methods of casting, and neither worked.

    What is going wrong here? The code compiles just fine. (There's more going on, of course, but these seem to be the relevant bits).

    The full text of the error is:
    "InvalidProgramException: Invalid IL code in Descriptor_Number:Increase (): IL_0026: stloc.1", and it triggers on the line noted below in the code.

    EDIT: Cleaned up the code from the original post for better clarity. Same problems, though.

    Code (CSharp):
    1. public class Descriptor : IComparable<Descriptor>, IEquatable<Descriptor>
    2. {
    3.    // Stuff goes here
    4. }
    5.  
    6. public class Descriptor_Number : Descriptor
    7. {
    8.     public string Value { get; set; } // There's more here, but for simplicity...
    9.  
    10.     // Increment Value
    11.     public void Increase()
    12.     {
    13.         // Code goes here, but is never reached
    14.     }
    15.  
    16.     // Decrement Value
    17.     public void Decrease()
    18.     {
    19.         // Code goes here, but is never reached
    20.     }
    21. }
    22.  
    23.  
    24. public abstract class MiniDescrListPanel : Monobehaviour
    25. {
    26.     protected Descriptor descriptor = null; // Later, a Descriptor_Number is stored here.
    27. }
    28.  
    29. // Attached to a GameObject. Methods are assigned to UI objects via the Inspector
    30. public class MiniDescrListPanel_Number : MiniDescrListPanel
    31. {
    32.     InputField valueInput = null; // Set to an InputField text object elsewhere
    33.  
    34.     // Called when a new value is entered in the InputField
    35.     public void InputText_Edit(string text)
    36.     {
    37.         if (descriptor is Descriptor_Number dn)
    38.         {
    39.             dn.Value = text; // Setting this property works just fine
    40.         }
    41.     }
    42.  
    43.     // A "+" button calls this method, assigned via the inspector
    44.     public void IncreaseButton_Click()
    45.     {
    46.         if (descriptor is Descriptor_Number dn)
    47.         {
    48.             dn.Increase(); // THIS IS WHERE THE ERROR OCCURS
    49.             valueInput.text = dn.Value; // This line is never reached
    50.         }
    51.     }
    52.  
    53.     // A "-" button calls this method, assigned via the inspector
    54.     public void DecreaseButton_Click()
    55.     {
    56.         if (descriptor is Descriptor_Number dn)
    57.         {
    58.             dn.Decrease(); // This triggers the same problem
    59.             valueInput.text = dn.Value; // Not reached
    60.         }
    61.     }
    62. }
    63.  
    Referenced in some older comments:
    Code (CSharp):
    1. public class MiniDescrListPanel_Number : MonoBehaviour
    2. {
    3.    // assigned a value of type Descriptor_Number in another method
    4.    protected Descriptor descriptor = null;
    5.    // assigned in another method
    6.    InputField valueInput = null;
    7.  
    8.     // triggered by end edit event in an InputField Text object, works fine.
    9.     public void InputText_Edit(string text)
    10.     {
    11.         if (!(descriptor is Descriptor_Number))
    12.             return;
    13.         (descriptor as Descriptor_Number).Value = text;
    14.     }
    15.  
    16.     // triggered by a button click event, assigned in the inspector
    17.     public void IncreaseButton_Click()
    18.     {
    19.         Descriptor_Number descrNumber = descriptor as Descriptor_Number;
    20.         if (descrNumber != null)
    21.         {
    22.             descrNumber.Increase();  // this call triggers the InvalidProgramException
    23.             valueInput.text = descrNumber.Value;
    24.         }
    25.     }
    26.  
    27.    // similar to Increase(), but tries a different method, same problem
    28.    public void DecreaseButton_Click()
    29.     {
    30.        // wish I could use (descriptor is not Descriptor_Number, but Unity doesn't like that format)
    31.        if (!(descriptor is Descriptor_Number))
    32.             return;
    33.  
    34.         (descriptor as Descriptor_Number).Decrease(); // this call triggers the InvalidProgramException
    35.         valueInput.text = (descriptor as Descriptor_Number).Value;
    36.     }
    37. }
    38.  
    39. public class Descriptor{}
    40. public class Descriptor_Number : Descriptor
    41. {
    42.    public string Value {get; set;}
    43.    public void Increase() {} // increases the Descriptor_Number.Value
    44.    public void Decrease() {} // Decreases the Descriptor_Number.Value
    45. }
    46.  
     
    Last edited: Jun 2, 2021
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    I'm not sure about the InvalidProgramException, but there is a simpler and cleaner way to do what you're doing.
    Code (CSharp):
    1. if (descriptor is Descriptor_Number dn)) {
    2.     dn.Decrease();
    3.     valueInput.text = dn.Value;
    4. }
    These probably also need to change (surprised this is not a compile error):
    Code (CSharp):
    1.    public void Increase {} // increases the Descriptor_Number.Value
    2.    public void Decrease{} // Decreases the Descriptor_Number.Value
    to
    Code (CSharp):
    1.    public void Increase() {} // increases the Descriptor_Number.Value
    2.    public void Decrease() {} // Decreases the Descriptor_Number.Value
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    Are you talking about
    System.Data.Services.Client.Descriptor
    ?

    If so, on my Unity 2021, System.Data.Services does not exist.

    Screen Shot 2021-05-04 at 4.03.35 PM.png
     
  4. RoughDiamond

    RoughDiamond

    Joined:
    Dec 14, 2019
    Posts:
    12
    No, Descriptor is a custom class.
     
  5. RoughDiamond

    RoughDiamond

    Joined:
    Dec 14, 2019
    Posts:
    12
    I do like that syntax better, thanks! I knew there was something not quite as nice as it should be.

    Unfortunately the console is rejecting it:
    InvalidProgramException: Invalid IL code in Descriptor_Number:Increase (): IL_0026: stloc.1 ​

    Oh, goodness, yes, those would have produced a compile error. Thankfully, the code that appeared in the OP was not my actual code, just snippets of it. (Also edited the OP to remove that distraction.)
     
  6. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    The exception you're getting is very strange. Normally it is something you would only expect to see when generating code at runtime using the System.Reflection.Emit namespace or something similar. Are you doing anything like that?
     
  7. RoughDiamond

    RoughDiamond

    Joined:
    Dec 14, 2019
    Posts:
    12
    No, nothing like that. I wish I was talented enough to get into that kind of trouble.
     
  8. RoughDiamond

    RoughDiamond

    Joined:
    Dec 14, 2019
    Posts:
    12
    Still having this issue: I was hoping an update might fix it.

    Here's the best simplified version of what's going on:
    Code (CSharp):
    1.  
    2. public class Descriptor : IComparable<Descriptor>, IEquatable<Descriptor>
    3. {
    4.    // Stuff goes here
    5. }
    6.  
    7. public class Descriptor_Number : Descriptor
    8. {
    9.     public string Value { get; set; } // There's more here, but for simplicity...
    10.  
    11.     // Increment Value
    12.     public void Increase()
    13.     {
    14.         // Code goes here, but is never reached
    15.     }
    16.  
    17.     // Decrement Value
    18.     public void Decrease()
    19.     {
    20.         // Code goes here, but is never reached
    21.     }
    22. }
    23.  
    24.  
    25. public abstract class MiniDescrListPanel : Monobehaviour
    26. {
    27.     protected Descriptor descriptor = null; // Later, a Descriptor_Number is stored here.
    28. }
    29.  
    30. // Attached to a GameObject. Methods are assigned to UI objects via the Inspector
    31. public class MiniDescrListPanel_Number : MiniDescrListPanel
    32. {
    33.     InputField valueInput = null; // Set to an InputField text object elsewhere
    34.  
    35.     // Called when a new value is entered in the InputField
    36.     public void InputText_Edit(string text)
    37.     {
    38.         if (descriptor is Descriptor_Number dn)
    39.         {
    40.             dn.Value = text; // Setting this property works just fine
    41.         }
    42.     }
    43.  
    44.     // A "+" button calls this method, assigned via the inspector
    45.     public void IncreaseButton_Click()
    46.     {
    47.         if (descriptor is Descriptor_Number dn)
    48.         {
    49.             dn.Increase(); // THIS IS WHERE THE ERROR OCCURS
    50.             valueInput.text = dn.Value; // This line is never reached
    51.         }
    52.     }
    53.  
    54.     // A "-" button calls this method, assigned via the inspector
    55.     public void DecreaseButton_Click()
    56.     {
    57.         if (descriptor is Descriptor_Number dn)
    58.         {
    59.             dn.Decrease(); // This triggers the same problem
    60.             valueInput.text = dn.Value; // Not reached
    61.         }
    62.     }
    63. }
    64.  
     
    Last edited: Jun 2, 2021
  9. RoughDiamond

    RoughDiamond

    Joined:
    Dec 14, 2019
    Posts:
    12
    Found the issue!

    Unity was balking at calling the
    Increase()
    method, because the method contained something it didn't know how to compile, the new-fangled null-coalescing operator from C# 8.0:

    (
    decimal? nums[]
    )

    Code (CSharp):
    1. // Increment Value
    2.     public void Increase()
    3.     {
    4.         if (nums[(int)NumIndex.Increment] != null)
    5.         {
    6.             //nums[(int)NumIndex.Value] ??= 0; // COMMENTING OUT THIS CODE ALLOWS THE REST TO RUN
    7.             nums[(int)NumIndex.Value] += nums[(int)NumIndex.Increment];
    8.             Clamp(ref nums[(int)NumIndex.Value]);
    9.         }
    10.     }
    The longer form, however, works as intended.
    Code (CSharp):
    1. // Increment Value
    2.     public void Increase()
    3.     {
    4.         if (nums[(int)NumIndex.Increment] != null)
    5.         {
    6.             if (nums[(int)NumIndex.Value] is null)
    7.                 nums[(int)NumIndex.Value] = 0;
    8.             nums[(int)NumIndex.Value] += nums[(int)NumIndex.Increment];
    9.             Clamp(ref nums[(int)NumIndex.Value]);
    10.         }
    11.     }