为什么将类型对象的动态类型转换为抛出空引用异常的对象?

bed*_*edo 62 .net c# dynamic nullreferenceexception

我有以下功能:

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;
}
Run Code Online (Sandbox Code Playgroud)

当我用以下方式调用它时,

object a = new object();
object v = TUtils.TryGetArrayValue<object>(new object[] { a }, 0);
Run Code Online (Sandbox Code Playgroud)

(T)boxed 抛出空引用异常.

除了"对象"之外,我放在那里的任何其他类型,它完全正常.
任何想法是什么,为什么它抛出异常?

编辑:我使用动态的原因是为了避免在转换类型时出现异常,例如:

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

Eri*_*ert 43

我同意其他回答说这看起来像个错误的回答者.具体来说,它似乎是C#运行时绑定层中的一个错误,虽然我没有彻底调查它.

我为错误道歉.我将它报告给C#5测试团队,我们将看看它是否已经在C#5中报告和修复.(它在最近的beta版本中重现,所以它不太可能已经被报告和修复. )如果没有,修复不太可能进入最终版本.在这种情况下,我们会考虑将其用于可能的服务发布.

谢谢让我们注意到这个.如果您想要输入Connect问题来跟踪它,请随意这样做,并请包含此StackOverflow问题的链接.如果你不这样做,没问题; 测试团队将以任何方式了解它.

  • @bedo:绝对的.格兰芬多十分! (28认同)

Ree*_*sey 14

这是动态工作原理的一个问题 - 运行时绑定程序存在转换问题System.Object,但实际上并不是问题.

我怀疑这是因为dynamic,在运行时,本身就是永远 System.Object.4.7中的C#语言规范:"动态类型在运行时与对象无法区分." 因此,任何用作动态的对象都只是作为对象存储.

当您将实际实例System.Object放入动态时,在运行时绑定解析中会出现一些导致空引用异常的内容.

但是,任何其他不起作用的System.Object类型 - 甚至引用类型等,没有缺陷.因此,这应该为您提供正确的行为,因为实际上没有理由创建一个System.Object可以传递的自身实例- 您总是希望某个子类具有其他类型信息.

只要您使用任何"真实"类型,这都可以正常工作.例如,以下工作,即使它已被传递并视为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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Eli*_*ing 6

这是非常奇怪的行为,它确实看起来像是一个执行中的错误dynamic.我发现这种变化不会引发异常并确实返回对象:

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

请注意,我必须在方法签名中添加泛型约束,因为as只有T作为引用类型,运算符才有效.

如果您正在寻找一种解决方法,您可以使用它(我知道它很难看):

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;
}
Run Code Online (Sandbox Code Playgroud)