2

これは私の最初のStackOverflow投稿なのでサイトを管理している人たちと積極的に他の人を支援してくれている人たちに心からの感謝を述べたいと思います。StackOverflowは、C#コードの課題を解決するのに非常に役立つリソースです。

クラスの説明:MS VisualStudio 2010 C#.NETコンソールアプリには、次の基本/派生階層があります。

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

...後者の3つは、それぞれ次の基本/派生階層のメンバーです。

  • 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また、問題のないメンバーpublicもありますが、それよりも深くオーバーライドされないDirEntry[] dir_entries;ことに注意してください(たとえば、ありません)。DirEntryDirectoryAudioDirEntry

問題: 型がまたはの場合に、基本クラスのメソッド内または他のクラスから共通メンバー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

問題は、プロパティまたはメソッドをオーバーライドすると、署名、つまり関連する型を変更できないという事実です。新しい修飾子を使用してこの制限を無視することはできますが、これが何を意味するかを十分に認識している必要があります(これについては後で詳しく説明します)。あなたの場合、サブクラスのプロパティの暗黙的な定義を避ける必要があります。これは、基本クラスのプロパティとは異なるサブクラスの新しい変数を宣言するためです。つまり、コードは次のようになります。

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

これは機能するはずですが、新しい修飾子を使用するとコンパイル時のバインドが強制されることに注意してください。これは、実行されるプロパティが、インスタンスの実際のタイプではなく、宣言された変数のタイプに依存することを意味します。たとえば、次のコードでは、AudioDirectoryのインスタンスが1つありますが、file_entriesの最初の呼び出しでAudioDirectoryバージョンが実行され、2番目の呼び出しで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.Directory.file_entries'と一致するには、タイプは'app1.FileEntry[]'である必要があります。"

基本クラスからオーバーライドするのと同じ型を返す必要があることを意味します。

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 に答える