0

これは、私が求めていることのかなり不自然な例です。

public partial class Form1 : Form
{
    private Fruit fruit;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        fruit = new Apple();

        Geneticist geneticist = new Geneticist(fruit);

        // Later on in program..

        geneticist.Engineer();

        Console.WriteLine(fruit.Color);

        // Still red because a copy of fruit was made in Geneticist class.
    }
}

class Fruit
{
    public string Color { get; set; }
}

class Apple : Fruit
{
    public Apple()
    {
        Color = "Red";
    }
}

class Banana : Fruit
{
    public Banana()
    {
        Color = "Yellow";
    }
}

class Geneticist
{
    private Fruit fruit;
    private Banana banana;

    public Geneticist(Fruit fruit)
    {
        this.fruit = fruit;
        this.banana = new Banana();
    }

    public void Engineer()
    {
        fruit = banana;
    }
}

基本的に、メイン フォームにフルーツをメンバー変数として格納しています。それを Geneticist クラスに渡し、後で値を再割り当てできるようにしたいと考えています。

Geneticist でフルーツを入力fruit = banana;すると、Form1 フルーツではなく、Geneticist のローカル コピーがポイントされます。ref キーワードをシミュレートする方法を探しています。ここで、遺伝学者の果物を再割り当てすると、Form1 の果物も変更で更新されます。

果物のラッパーを作成して、代わりにそれを渡すことができると思いますが、それは少しハックのようです。またEngineer、メインフォームが値を再割り当てできるようにメソッドにイベントを発生させることもできますが、プログラムの多くの部分でそれを行う必要があるのも少し面倒です。

また、refGeneticist のコンストラクターではなく、後で変更するため、キーワードを使用できません。

読んでくれてありがとう!

4

1 に答える 1

4

これに伴う問題は、再割り当てしても、Form1の元のファイルには影響しないことです。私がfruit=bananaと入力すると、遺伝学者でコピーが作成されます。

いいえ、これは間違っています。コピーは作成されません。

何が起こるかというと、手元にAppleある参照を。への参照で上書きしますBanana。まるでリンゴをポケットに入れてもらい、しばらく握った後、地面に置いてバナナを手に取り、ポケットに入れます。

後で、元のリンゴを食べることにしたとき、元のリンゴは無傷になりますが、コピーを作成したからではありません。あなたがそれに興味を失い、代わりに全く無関係の果物を手に入れたという理由だけで。

じゃあ何をすればいいの?

参照セマンティクスを使用してパラメーター全体を変更することはできないという事実が残っていますFruit(CLRでは、自分で言ったように、参照をクラスメンバーとして格納することはできません)。

Geneticist参照を変更する場合Fruitは、その周りにラッパーを作成する必要があります。しかし、最も実用的な解決策は、呼び出し元のコードを以下と連携させることですGeneticist

class Geneticist
{
    private Fruit fruit;
    private Banana banana;

    public Geneticist(Fruit fruit)
    {
        this.fruit = fruit;
        this.banana = new Banana();
    }

    public Fruit Engineer()
    {
        fruit = banana;
        return fruit; // return the new value
    }
}

そして、呼び出しコード:

fruit = new Apple();

Geneticist geneticist = new Geneticist(fruit);
fruit = geneticist.Engineer(); // use the return value this way
Console.WriteLine(fruit.Color);

別の実行可能なアプローチ

Geneticist果物自体を変更する方法を知ってもらうのはどうですか?

class Geneticist
{
    private Fruit fruit;

    private readonly Banana banana;

    private readonly Action<Fruit> engineer;

    public Geneticist(Fruit fruit, Action<Fruit> engineer)
    {
        this.fruit = fruit;
        this.banana = new Banana();
        this.engineer = engineer;
    }

    public void Engineer()
    {
        this.engineer(this.banana);
    }
}

そして、呼び出しコード:

Fruit fruit = new Apple();
Geneticist geneticist = new Geneticist(fruit, f => { fruit = f; });
geneticist.Engineer();
Console.WriteLine(fruit.Color);
于 2011-09-16T23:19:01.367 に答える