web-dev-qa-db-ja.com

C#サブクラスのメンバー変数(フィールド)を非表示ではなくオーバーライドするにはどうすればよいですか?

これにより、ItemAとItemBの両方の名前がわかります。 「Subitem\nSubitem」と表示されるはずですが、代わりに「Item\nSubitem」と表示されます。これは、Subitemクラスで定義された "Name"変数が、基本的には基本Itemクラスで定義された "Name"変数とは異なるためです。元の変数を新しい値に変更したい。仮想とオーバーライドがメソッドで完全に機能することを考えると、これが今までにないほど簡単なことではない理由がわかりません。 実際にオーバーライドする変数の方法を見つけることはできませんでした。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine(ItemA.Name);
            System.Console.WriteLine(ItemB.Name);
            System.Console.ReadKey();
        }
        static Item ItemA = new Subitem();
        static Subitem ItemB = new Subitem();
    }
    public class Item
    {
        public string Name = "Item";
    }
    public class Subitem : Item
    {
        new public string Name = "Subitem";
    }
}
30
Eagle-Eye

C#ではoverride変数は使用できませんが、プロパティは上書きできます。

public class Item
{
    public virtual string Name {get; protected set;}
}
public class Subitem : Item
{
    public override string Name {get; protected set;}
}

別のアプローチは、次のようにサブクラスの値を変更することです:

public class Item
{
    public string Name = "Item";
}
public class Subitem : Item
{
    public Subitem()
    {
        Name = "Subitem";
    }
}
34
dasblinkenlight

フィールド(変数と呼ばれるもの)には、ポリモーフィズム(overrideが機能させるもの)の概念はありません。代わりにここで使用する必要があるのはプロパティです。

public class Item
{
    public virtual string Name
    {
        get { return "Item"; }
    }
}

public class SubItem : Item
{
    public override string Name
    {
        get { return "Subitem"; }
    }
}
8
Adam Robinson

「変数のオーバーライド」とはどういう意味ですか?

変数は、概念的なメモリ内の名前付きの場所です(フィールドの場合はあまりありませんが、レジスタである可能性があるため、「概念」)。

メソッドをオーバーライドすると、ある操作セットが別の操作セットに置き換えられます。

メモリ内の名前付きの場所は一連の操作ではないため、どのように置き換えることができますか?メモリ内の指定された場所を使用することを想定していることは何ですか?

メモリに保存されているものを変更したい場合は、派生クラスが構築されたときに変更してください:

public class Item
{
  public string Name = "Item";
}
public class Subitem : Item
{
  public SubItem()
  {
    Name = "Subitem";
  }
}

操作のセットとしてオーバーライドする場合は、オーバーライドする操作のセット(メソッドまたはプロパティ)を定義します。

5
Jon Hanna

この質問は比較的古く、作者はおそらくC#5.0以下を使用していました。しかし、同じ質問があり、C#6.0以降で動作する非常にきちんとしたソリューションを見つけました。

C#6.自動プロパティを初期化する機能を提供します。だからそれを使うことができます:

public class Item
{
    public virtual string Name { get; set; } = "Item";
}

public class Subitem : Item
{
    public override string Name { get; set; } = "Subitem";
}
2
x3ro

可能な解決策は、次のようにプロパティを使用して、そのgetterをオーバーライドすることです。

public class Item
{
    public virtual string Name { get { return "Item"; } }
}
public class Subitem : Item
{
    public override string Name { get { return "Subitem"; } }
}
1
Jesse Emond