为什么要将types对象的dynamic转换为抛出空引用exception的对象?

我有以下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; } 

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

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

(T)boxed引发空引用exception。

除了“对象”之外,我还有其他types的东西,它工作的很好。
任何想法是什么,以及为什么抛出exception?

编辑:我使用dynamic的原因是在转换types时避免exception,例如:

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

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

我为错误表示歉意。 我将把它报告给C#5testing团队,我们将看看它是否已经在C#5中报告和修复(它在最近的beta版本中复制,所以它不太可能已经被报告和修复。 )如果不是的话,一个修复不太可能进入最终版本。 在这种情况下,我们会考虑可能的维修版本。

谢谢让我们注意到这个。 如果您想进入连接问题来跟踪它,请随时这样做,请包括一个链接到这个StackOverflow的问题。 如果你不这样做,没问题; testing团队将会了解这一点。

这是dynamic工作的一个问题 – 运行时绑定程序与来自System.Object转换有关的问题,但实际上,这不是问题。

我怀疑这是因为在运行时dynamic本身总是 System.Object 。 4.7中的C#语言规范声明:“dynamictypes在运行时与对象无法区分”。 因此,任何用作dynamic的对象都只是作为一个对象来存储。

当你把一个实际的System.Object实例变成一个dynamic的时候,在运行时绑定parsing中会发生一些引起null引用exception的东西。

但是, 任何不是System.Object 其他types都可以工作 – 即使是引用types等,也没有缺陷。 因此,这应该为您提供适当的行为,因为实际上没有理由创build一个System.Object本身的实例,它将被传递 – 您总是需要其他types信息的子类。

只要你使用任何“真正的”types,这工作正常。 例如,下面的工作,即使它被传递和对待:

 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(); } } 

这真是奇怪的行为,它确实看起来像是在执行dynamic的错误。 我发现这个变体不会抛出exception,并确实返回对象:

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

请注意,我必须在方法签名中添加通用约束,因为as运算符只在T是引用types时才起作用。

如果你正在寻找一个解决方法,你可以使用这个(我知道这是丑陋的):

 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; } 

它与dynamic关键字有关。 如果我改变types为T盒装它的作品。

  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; } 

是否有一个特定的原因,你正在使用dynamic? 在这种情况下,你真的不需要它,因为你知道什么types提前。 如果你看,在你的版本中,boxed的types不是对象,而是dynamic的{object},当试图转换成object时可能是问题。 如果你看看我发布的这个版本,你会得到一个types的对象,没有错误。