Why is casting a dynamic of type object to object throwing a null reference exception?

C#.NetDynamicNullreferenceexception

C# Problem Overview


I have the following function:

public static T TryGetArrayValue<T>(object[] array_, int index_)
{
    ... //some checking goes up here not relevant to question

    dynamic boxed = array_[index_];
    return (T)boxed;
}

When I call it in the following way,

object a = new object();
object v = TUtils.TryGetArrayValue<object>(new object[] { a }, 0);

(T)boxed throws a null reference exception.

Any other type I put in there other than "object", it works perfectly fine.
Any ideas what this is, and why it's throwing the exception?

Edit: The reason why I use dynamic is to avoid exception when converting types, for example:

double a = 123;
int v = TUtils.TryGetArrayValue<int>(new object[] { a }, 0);

C# Solutions


Solution 1 - C#

I agree with the other answerers who say that this looks like a bug. Specifically it appears to be a bug in C# runtime binding layer, though I have not investigated it thoroughly.

I apologize for the error. I'll report it to the C# 5 testing team and we'll see if it has already been reported and fixed in C# 5. (It reproduces in the recent beta release, so it is unlikely that it has already been reported and fixed.) If not, a fix is unlikely to make it into the final release. In that case we'll consider it for a possible servicing release.

Thanks for bringing this to our attention. If you feel like entering a Connect issue to track it, feel free to do so and please include a link to this StackOverflow question. If you don't, no problem; the test team will know about it either way.

Solution 2 - C#

This is an issue with how dynamic works - the runtime binder has an issue with conversions from System.Object, but in practice, is really not an issue.

I suspect this is because dynamic, at runtime, is itself always System.Object. The C# Language Spec in 4.7 states: "The type dynamic is indistinguishable from object at run-time." As such, any object used as dynamic is just stored as an object.

When you put an actual instance of System.Object into a dynamic, something is occuring within the runtime binding resolution which causes a null reference exception.

However, any other type that isn't System.Object works - even reference types and the like, without flaws. As such, this should provide you the proper behavior, since there really are no reasons to create an instance of System.Object itself which would be passed around - you'd always want some subclass with other type information.

As soon as you use any "real" type, this works fine. For exmaple, the following works, even though it's passed and treated as Object:

public class Program
{
    public static T TryGetArrayValue<T>(object[] array_, int index_)
    {

        dynamic boxed = array_[index_];
        return (T)boxed;
    }

    private static void Main()
    {
        int p = 3;
        object a = p;
        var objects = new[] { a, 4.5 };

        // This works now, since the object is pointing to a class instance
        object v = TryGetArrayValue<object>(objects, 0);
        Console.WriteLine(v);

        // These both also work fine...
        double d = TryGetArrayValue<double>(objects, 1);
        Console.WriteLine(d);
        // Even the "automatic" int conversion works now
        int i = TryGetArrayValue<int>(objects, 1);
        Console.WriteLine(i);
        Console.ReadKey();
    }
}

Solution 3 - C#

This is really strange behavior, and it indeed looks like a bug in the implementation of dynamic. I discovered that this variation does not throw an exception and indeed returns the object:

public static T TryGetArrayValue<T>(object[] array, int index) where T : class
{
	dynamic boxed = array[index];
	return boxed as T;
}

Note that I had to add a generic constraint in the method signature because the as operator only works if T is a reference type.

If you are looking for a workaround, you could use this (and I know it's ugly):

public static T TryGetArrayValue<T>(object[] array, int index)
{
	dynamic boxed = array[index];

	if (typeof(T) == typeof(object))
		return (T)(boxed as object);

	return (T)boxed;
}

Solution 4 - C#

It has something to do with the dynamic keyword. If I change the type to T for boxed it works.

    static void Main(string[] args)
    {
        object a = new object();
        object v = TryGetArrayValue<object>(new object[] { a }, 0);

        Console.ReadLine();
    }

    public static T TryGetArrayValue<T>(object[] array_, int index_)
    {

            T boxed = (T)array_[index_];
            return boxed;
      
    }

Is there a particular reason that you are using dynamic? You really don't need it in this case as you know what the type is ahead of time. If you look, in your version the type of boxed isn't object but it is dynamic{object} which could be the issue when trying to cast to object. If you look at this version that I posted, you get a type of object and no errors.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbedoView Question on Stackoverflow
Solution 1 - C#Eric LippertView Answer on Stackoverflow
Solution 2 - C#Reed CopseyView Answer on Stackoverflow
Solution 3 - C#Elian EbbingView Answer on Stackoverflow
Solution 4 - C#JettiView Answer on Stackoverflow