0

Hello can someone please explain me how can one object pass through a NULL guard then throws exception when trying to acess non-nullable field? (bool)

As you can see in the method above our object response of type Node is not null.Focus your attention on the boolean field IsArray !!

enter image description here

Lets see what happens when our response enters the Deserialize method:

Node is not null before entering Deserialize method

                                   Passes null guard !!

enter image description here

Then crashes with Null Reference Exception on an non-nullable field.Exactly on the field i said to focus: the boolean IsArray.

Stack Trace

{System.NullReferenceException: Object reference not set to an instance of an object.
   at redius.Node.get_Kind() in D:\Work\redius\core\redius\Internals\Resp\Node.cs:line 15
   at redius.Node.get_IsArray() in D:\Work\redius\core\redius\Internals\Resp\Node.cs:line 22
   at redius.Deserializer.List.Deserialize(Node node) in D:\Work\redius\core\redius\Internals\Formatter\Deserializer\Deserializer.List.cs:line 19}

Can someone please explain me how is this possible?Below is the Node type:

public abstract partial class Node : IEquatable<Node> {

        public enum Discriminator {
            String,
            Integer,
            Array
        }

        public Discriminator Kind => this.NodeKind;
        protected abstract Discriminator NodeKind { get; }

        public Node.Array AsArray => this as Node.Array;
        public Node.Integer AsInteger => this as Node.Integer;
        public Node.String AsString => this as String;

        public bool IsArray => this.Kind == Discriminator.Array;
        public bool IsString => this.Kind == Discriminator.Integer;
        public bool IsInteger => this.Kind == Discriminator.String;

        #region IRAW

        protected virtual ReadOnlyMemory<byte> GetRaw() {
            return new byte[] { };
        }

        #endregion

        public bool Equals(Node other) {
            if (this.Kind != other.Kind) {
                return false;
            }
            bool result;
            switch (other.Kind) {
                case Discriminator.Array: result = this.AsArray.Equals(other.AsArray); break;
                case Discriminator.Integer: result = this.AsInteger.Equals(other.AsInteger); break;
                case Discriminator.String: result = this.AsString.Equals(other.AsString); break;

                default: throw new NotImplementedException();
            }
            return result;
        }

    }

P.S: When the Node enters the Deserialize method something goes wrong with the debugger since i can't acess it (can not acess its fields) !

P.S 2 If i try to add the following line in the Deserializer method :
var values = node.GetType().GetFields().Select(x => x.GetValue(node));
the application enters a break state and i get the following exception :
System Execution Engine Exception

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
Bercovici Adrian
  • 8,794
  • 17
  • 73
  • 152
  • 1
    Post the actual, full exception including the call stack. You can get that easily by calling `Exception.ToString()`. I'd bet call stack shows that the exception is thrown by the null guard of *another* thread. Throw an `ArgumentNullException` with an explanation instead of the generic `NullReferenceException()`, eg `throw new ArgumentNullException(nameof(node))` – Panagiotis Kanavos Sep 03 '18 at 14:22
  • Check my last line.I get an engine exception if i try to get the value of the fields.However the fields are present when entering the method as you can see in the first snippet. – Bercovici Adrian Sep 03 '18 at 14:31
  • The first *image* doesn't show any exceptions. *Please post the actual exception, including the call stack*. Posting the *name* of the exception doesn't help at all. And *do* use the appropriate exception, `ArgumentNullException`. You *don't* need to access any fields, just log the result of `Exception.ToString()` in your exception handler – Panagiotis Kanavos Sep 03 '18 at 14:35
  • Well the first image is posted to show you that the object in case is not null before it enters the `Deserialize` method ! It somehow becomes `NULL` inside the method and throws exception. – Bercovici Adrian Sep 03 '18 at 14:36
  • Are you sure you aren't looking at a *different* thread? Post the exception please. It's impossible to reproduce the problem or guess what's wrong from screenshots and incomplete information. Without the call stack it's impossible which code path resulted in the exception – Panagiotis Kanavos Sep 03 '18 at 14:38
  • I do not have multiple threads in this application. – Bercovici Adrian Sep 05 '18 at 12:28
  • Did you check the call stack snippet you posted? The exception is thrown by the `redius.Node.Kind` getter. Not by `node.IsArray` or the guard clause. The getter calls the abstract NodeKind property which isn't shown here. Without knowing what the actual implementation of NodeKind is, only you can find the problem by debugging the code when the exception occurs. You didn't post the *full* exception either. There may be an inner exception thrown/rethrown by `NodeKind`. Just use `Exception.ToString()` to get the entire exception, inner exceptions and all call stacks and post that. – Panagiotis Kanavos Sep 05 '18 at 12:39
  • Please post code that actually reproduces the problem. Right now people have to guess a lot - what the actual exception is, where it was thrown, what code was actually called, what the property values are – Panagiotis Kanavos Sep 05 '18 at 12:41
  • Ok i have solved it.The problem was not related.I was using the `ILGenerator` and to generate the `ProcessAsync` method and i have mistaken the return type.It can be closed. – Bercovici Adrian Sep 05 '18 at 13:13
  • @BercoviciAdrian, Since you have resoled this issue, would you please convert your comment to the answer? This can be beneficial to other community members reading this thread and we close this thread :). – Leo Liu Sep 06 '18 at 01:31

0 Answers0