C# NullReferenceException引用来自基类的派生成员对象的公共成员
由于这是我的第一篇StackOverflow帖子,我想简单地说一句,非常感谢那些管理这个网站的人和那些积极为他人提供帮助的人。StackOverflow在解决C#代码挑战方面是非常有用的资源 类描述:在MS VisualStudio 2010 C#NET控制台应用程序中,我具有以下基本/派生层次结构:C# NullReferenceException引用来自基类的派生成员对象的公共成员,c#,.net,polymorphism,base,derived,C#,.net,Polymorphism,Base,Derived,由于这是我的第一篇StackOverflow帖子,我想简单地说一句,非常感谢那些管理这个网站的人和那些积极为他人提供帮助的人。StackOverflow在解决C#代码挑战方面是非常有用的资源 类描述:在MS VisualStudio 2010 C#NET控制台应用程序中,我具有以下基本/派生层次结构: Entry->DirEntry Entry->FileEntry->AudioFileEntry->OutputFileEntry …后三个分别是以下基本/派生层次结构中的成员: 目录->音
->Entry
DirEntry
->Entry
->FileEntry
->AudioFileEntry
OutputFileEntry
->目录
->音频目录
输出目录
具有成员目录
公共文件项[]文件项代码>
具有成员AudioDirectory
公共AudioFileEntry[]文件项代码>
具有成员OutputDirectory
公共OutputFileEntry[]文件项代码>
条目
以以下方式声明:
public class Entry : IComparable
{
public string name;
public int entryID;
public int parentID;
//(other code omitted)
}
目录
也有成员publicDirEntry[]diru项
没有问题,但请注意,DirEntry
的覆盖深度不超过目录(例如,没有AudioDirEntry
)
问题:NullReferenceException
试图从基类目录方法中读取文件项[n]
中的公共成员,或者在类型为AudioDirectory
或OutputDirectory
时从其他类读取公共成员
没有相关的类、成员或方法是静态的。我尝试过使用new
和override
但没有效果。试图将文件\u条目
设置为属性:
public class Directory
{
public virtual FileEntry[] file_entries { get; set; }
}
public class AudioDirectory : Directory
{
public override AudioFileEntry[] file_entries { get; set; }
//(other code omitted)
}
…失败,错误为“…”app1.AudioDirectory.file_entries”:类型必须为“app1.FileEntry[]”,才能与重写的成员“app1.Directory.file_entries”匹配。
”
目标:在基类目录
方法中引用文件项
的能力,无论对象是哪种派生类型。我的直觉告诉我,我可能忽略了一些简单的事情,因为上面提到的就是多态性的本质,应该有一种方法来实现这一点,而不必求助于新的动态类型
建议
-涡轮
“'app1.AudioDirectory.file_entries':类型必须为'app1.FileEntry[]”才能
匹配覆盖的成员“app1.Directory.file_entries”
意味着您需要返回从基类重写的相同类型:
public class Directory
{
public virtual FileEntry[] file_entries { get; set; }
}
public class AudioDirectory : Directory
{
public override FileEntry[] file_entries {
get
{
return new AudioFileEntry[] { new AudioFileEntry() };
}
set
{
//(other code omitted)
}
}
}
如果您有其他问题,请提供所有代码。您的问题是,当您重写属性或方法时,您无法更改签名,即所涉及的类型。您可以使用新的修改器忽略此限制,但您必须清楚这意味着什么(稍后将对此进行详细介绍)。在您的例子中,您必须避免子类中属性的隐式定义,因为这将在子类中声明一个不同于基类中的新变量。我的意思是,您的代码将与此相同:
public class Directory
{
private FileEntry[] _file_entries;
public virtual FileEntry[] file_entries
{
get { return _file_entries; }
set{_file_entries = value;}
}
}
public class AudioDirectory
{
private AudioFileEntry[] _sub_file_entries;
public new AudioFileEntry[] file_entries
{
get { return _sub_file_entries; }
set{_sub_file_entries = value;}
}
}
这意味着当您在AudioDirectory中设置file_条目时,基类中访问的变量仍然为null
一个可能的解决方案是:
public class Directory
{
private FileEntry[] _file_entries;
public virtual FileEntry[] file_entries
{
get { return _file_entries; }
set{_file_entries = value;}
}
}
public class AudioDirectory : Directory
{
public new AudioFileEntry[] file_entries
{
get { return (AudioFileEntry[])base.file_entries; }
set { base.file_entries = value; }
}
}
这应该是可行的,但要注意使用新的修饰符会强制编译时绑定,这意味着执行的属性取决于声明变量的类型,而不是实例的实际类型。例如,在下面的代码中,您有一个AudioDirectory实例,但第一次调用file_条目执行AudioDirectory版本,第二次调用目录版本:
AudioDirectory ad = new AudioDirectory();
Directory d = ad;
FileEntry[] fa = ad.file_entries;
FileEntry[] fb = d.file_entries;
谢谢,伙计们。这听起来确实是动态类型的一个很好的例子,尽管在阅读了这两个回复之后,我意识到一个更简单而且可能运行时更快的解决方案是创建一个包装器类。令人惊讶的是,这是必要的,而且我所追求的多态性没有内置,但这显然是一个缺点,或者至少是C#现有设计的一个缺点。我会将AudioFileEntry更改为AudioFileDetails,将OutputFileEntry更改为OutputFileDetails,FileEntry将两者都作为成员与Entry一起使用。因为它不受支持,所以不会有实际的继承……公平地说,我想补充一点,我所追求的多态性似乎是通过新的动态类型得到支持的,我在运行时性能不太受关注的领域中的其他地方实现了新的动态类型。