为什么C#在转发后将实例的先前非null成员视为null?

Sau*_*aul 1 .net c# clr inheritance

在开发用于通过JSON与外部数据库通信的类库时,出现了一个有趣的问题,即对象实例的向上转换导致其先前的非空成员之一显示为null.

在试图弄清楚这种奇怪的原因时,许多头发被撕掉了,但到目前为止,我找不到合理的解释是不成功的.

以下是此问题的示例:

using System;
namespace Test
{
    public class Program
    {
        static void Main(string[] args)
        {
            Descendant d = new Descendant();
            d.Attributes.ToString(); // Everything fine here
            Ancestor a = (Ancestor)d;
            a.Attributes.ToString(); // NullPointerException
        }
    }

    class Ancestor
    {
        public interface IAttributes { }
        public IAttributes Attributes;
    }

    class Descendant : Ancestor
    {
        public new DescendantAttributes Attributes;

        public Descendant()
        {
            this.Attributes = new DescendantAttributes();
        }

        public class DescendantAttributes : IAttributes
        {
            public string Name = "";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

错误消息:System.NullReferenceException在D:\ Code\c#\ Test\Program.cs中的Test.Program.Main(String [] args)未处理:第12行

.NET版本:4.0

环境:64位Windows 2008 R2,Visual Studio 2010

为什么会这样?我的意思是,除非它有一个bug,否则它背后可能有一个设计理由.什么样的情况可以保证CLR在转发后将实例的先前非null成员视为null?

che*_*dep 6

使用new修饰符时,您隐藏了继承的属性.

public new DescendantAttributes Attributes;
Run Code Online (Sandbox Code Playgroud)

请看下面的链接http://msdn.microsoft.com/en-us/library/vstudio/435f1dw2.aspx

When used as a modifier, the new keyword explicitly hides a member that's inherited from a
base class. When you hide an inherited member, the derived version of the member replaces the
base-class version. You can hide members without using the new modifier, but the result is a
warning. If you use new to explicitly hide a member, the modifier suppresses this warning and
documents the fact that the derived version is intended as a replacement.
Run Code Online (Sandbox Code Playgroud)