2

由于这是我的第一篇 StackOverflow 帖子,我想简短地向管理该网站的人以及积极为他人提供帮助的人表示衷心的感谢StackOverflow 一直是解决 C# 代码挑战的非常有用的资源。

类描述:在 MS VisualStudio 2010 C# .NET 控制台应用程序中,我具有以下基本/派生层次结构:

  • Entry->DirEntry
  • Entry-> FileEntry-> AudioFileEntry->OutputFileEntry

...后三个分别是以下基本/派生层次结构中的成员:

  • Directory-> AudioDirectory->OutputDirectory

...这样:

  • Directory 有会员public FileEntry[] file_entries;
  • AudioDirectory 有会员public AudioFileEntry[] file_entries;
  • OutputDirectory有会员public OutputFileEntry[] file_entries;

基类Entry的声明方式如下:

public class Entry : IComparable
{
    public string name;
    public int entryID;
    public int parentID;
    //(other code omitted)
}

Directory也有DirEntry[] dir_entries;没有问题的成员 public,但请注意DirEntry不会被覆盖的更深(例如,Directory没有)。AudioDirEntry

问题: 当类型为或时,NullReferenceException尝试从基类方法或其他类中读取公共成员。file_entries[n]DirectoryAudioDirectoryOutputDirectory

没有相关的类、成员或方法是静态的。我试过使用newoverride无济于事。尝试创建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有一种方法可以在不求助于新类型的情况下实现这一点。

建议?

-涡轮

4

2 回答 2

3

您的问题是,当您覆盖属性或方法时,您无法更改签名,即所涉及的类型。您可以使用 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 时,在基类中访问的变量仍然为空。

一个可能的解决方案是:

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 修饰符会强制编译时绑定,这意味着执行的属性取决于声明变量的类型,而不是实例的实际打字错误。例如,在以下代码中,您有一个 AudioDirectory 实例,但第一次调用 file_entries 执行的是 AudioDirectory 版本,第二次调用的是 Directory 版本:

        AudioDirectory ad = new AudioDirectory();
        Directory d = ad;

        FileEntry[] fa = ad.file_entries;
        FileEntry[] fb = d.file_entries;
于 2012-09-26T10:49:07.483 回答
0

“'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)
        } 
    }
}

如果您有其他问题,请提供您的所有代码。

于 2012-09-26T10:31:11.010 回答