由于这是我在 StackOverflow 上发表的第一篇文章,我想对那些管理该网站的人和那些积极向他人提供帮助的人表示巨大的感谢。 StackOverflow 是解决 C# 代码挑战的非常有用的资源。
类描述:在 MS VisualStudio 2010 C# .NET 控制台应用程序中,我有以下基本/派生层次结构:
-
Entry
->DirEntry
-
Entry
->FileEntry
->AudioFileEntry
->OutputFileEntry
...后三个分别是以下基/派生层次结构中的成员:
-
Directory
->AudioDirectory
->OutputDirectory
...这样:
-
Directory
已有成员(member)public FileEntry[] file_entries;
-
AudioDirectory
已有成员(member)public AudioFileEntry[] file_entries;
-
OutputDirectory
已有成员(member)public OutputFileEntry[] file_entries;
基类Entry
通过以下方式声明:
public class Entry : IComparable
{
public string name;
public int entryID;
public int parentID;
//(other code omitted)
}
Directory
还有成员(member)公众DirEntry[] dir_entries;
这没有问题,但请注意DirEntry
不会被覆盖得比Directory
更深(例如,没有 AudioDirEntry
)。
问题: NullReferenceException
尝试读取file_entries[n]
内的常见成员从基类内部 Directory
当类型为 AudioDirectory
时,方法或来自其他类或OutputDirectory
.
没有相关的类、成员或方法是静态的。我尝试过使用 new
和override
无济于事。尝试制作file_entries
属性:
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': type must be 'app1.FileEntry[]' to match overridden member 'app1.Directory.file_entries'
”
目标: 能够引用 file_entries
在基类Directory
方法,无论对象是哪种派生类型。我的直觉告诉我,我可能忽略了一些简单的事情,因为以上本质上就是多态性的全部内容,并且应该有一种方法可以实现这一点,而无需诉诸新的 dynamic
类型。
建议?
-涡轮机
最佳答案
您的问题是,当您重写属性或方法时,您无法更改签名,即涉及的类型。您可以使用 new 修饰符忽略此限制,但您必须充分了解这意味着什么(稍后会详细介绍)。在您的情况下,您必须避免在子类中隐式定义属性,因为这会在子类中声明一个与基类中的变量不同的新变量。我的意思是你的代码将与此相同:
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_entries 时,基类中访问的变量仍然为 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; }
}
}
这应该可行,但要注意使用 new 修饰符强制编译时绑定(bind),这意味着执行的属性取决于声明变量的类型,而不是实例的实际拼写错误。例如,在以下代码中,您有一个 AudioDirectory 实例,但第一次调用 file_entries 执行 AudioDirectory 版本,第二次调用执行 Directory 版本:
AudioDirectory ad = new AudioDirectory();
Directory d = ad;
FileEntry[] fa = ad.file_entries;
FileEntry[] fb = d.file_entries;
关于c# - NullReferenceException 引用基类派生成员对象的公共(public)成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12599489/