4

動作していないコードがあります。皆さんが私に提供してくれる助けをいただければ幸いです。

以下のコードは例外を生成しています...しかし、refのセマンティクスを誤って解釈していない限り、例外は発生しないはずです。

編集:すべての答えに感謝します...私はOne.Produceメソッドで新しいQueueオブジェクトをインスタンス化していることを知っています...しかしこれは私が実際にやりたいことです、私はMain._queueに参照を保持させたいですOne._queueに。それは可能ですか?

using System;
using System.Collections.Generic;

namespace ConsoleApplication2
{
    class One
    {
        Queue<string> _queue;

        public One(ref Queue<string> queue)
        {
            // should be assigning by reference
            _queue = queue;
        }

        public void Produce()
        {
            _queue = new Queue<string>();
            _queue.Enqueue("one");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Queue<string> _queue = new Queue<string>();

            One one = new One(ref _queue);
            one.Produce();

            // this generates an exception, since _queue is empty
            // i'd have thought _queue would have one item, "one"
            string value = _queue.Dequeue();
        }
    }
}
4

8 に答える 8

3

問題は、関数Produceで新しいものをインスタンス化し、Queueこれをプライベートメンバーに割り当てていることOne._queueです。One._queueこれにより、コンストラクターで行った割り当てが上書きされます。ただし、ローカルとは、キューに入れたことのない_queue別の場所を指します。Queue<string>

Produceの最初の行を削除して次の情報を取得することで、これを修正できます。

public void Produce() {
        _queue.Enqueue("one");
}

ちなみに、_queue達成しようとしていることを達成するために、コンストラクターに参照を渡す必要はありません。つまり、以下も機能します

public One(Queue<string> queue) {
    _queue = queue;
}

参照による受け渡しは、コンストラクターの実行後に_queue、mainのローカルが別のインスタンスを参照するようにする場合に使用されます。Queue<string>One

于 2009-11-04T02:19:45.137 に答える
1

次のことを試してください。

    public One(Queue<string> queue)
    {
        // should be assigning by reference
        _queue = queue;
    }

    public void Produce()
    {
        _queue.Enqueue("one");
    }
于 2009-11-04T02:20:24.387 に答える
1

メソッド内で、次のProduce()行を削除します。

_queue = new Queue<string>();

ここで、新しいキューインスタンスを作成しています。

于 2009-11-04T02:21:08.630 に答える
0

one.Produce()は、_queueを新しい「空の」Queue()に置き換えます。これが、string value = _queue.Dequeue()がエラーをスローしている理由です(b / c _queue)

于 2009-11-04T02:18:57.767 に答える
0

Produceメソッドから次の行を削除します。

_queue = new Queue<string>();

Queue<String>これは、新しいへの新しい参照を使用して、参照によって渡す既存のへの参照を消去しますQueue<String>

于 2009-11-04T02:21:40.413 に答える
0

問題

問題は、refキーワードが宣言されたメソッドにのみ影響することです。したがって、コンストラクタでMainキューを変更することはできますが、メソッドで変更することはできません。OneProduce

あなたのコードでOneは、同じキューオブジェクトへの2番目の参照を作成しています。このProduceメソッドは、この2番目の参照を変更するだけです。

つまり、参照によってパラメーターを渡すメソッドを呼び出すと、呼び出されたメソッドは参照されたオブジェクトを変更できますが、これはこの呼び出しサイトでのみ可能です。呼び出しが戻った後、メソッド_queueで変数によって参照されるオブジェクトはすべてMainそこに残ります。

もう1つの考慮事項。のコンストラクターでの割り当て(「参照による割り当てOne」とコメントした場合)は、キーワードがない場合とまったく同じように機能します。割り当てが逆にされた場合にのみ、キーワードが違いを生みます。refqueue = _queue;ref


ソリューションA-Holder<T>クラス

Holder理にかなっているかもしれない1つの解決策は、次のようなクラスを作成することです。

public class Holder<T> {
    public T { get; set; }
}

次に、OneクラスはHolder<Queue<string>>オブジェクトに対して機能します。このMain方法も機能する必要がありHolder<Queue<string>>ます。このようにOne、キューインスタンスを変更でき、に反映されMainます。

はいはい。私はこの解決策が非常に厄介であることを知っていますが、あなたの質問の要件は私にも厄介なようです。それは修辞的な質問ですか?それとも、ここでより大きな問題を解決しようとしていますか?後者の場合、この大きな問題が何であるかを知りたいと思います。


ソリューションB-ポインター

別の解決策は、ポインタを使用することです。C#で実行することは完全に可能ですが、まったくお勧めしません。興味があれば、ポインタを使って解決策を書いてみてください。


ソリューションC-単一位置配列

あなた自身の答えは私に3番目の可能な解決策のアイデアを与えました。これは本質的に他の2つのソリューションと非常によく似ています。英語で説明するのではなく、C#で表示させてください。

class One
{
    Queue<string>[] queueArray;

    public One(Queue<string>[] queueArray)
    {
        if (queueArray == null) throw new ArgumentNullException("queueArray");
        if (queueArray.Length != 1) throw new ArgumentException("queueArray must have one and only one item");
        this.queueArray = queueArray;
    }

    public void Produce()
    {
        queueArray[0] = new Queue<string>();
        queueArray[0].Enqueue("one");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var queueArray = new Queue<string>[] { new Queue<string>() };

        One one = new One(queueArray);
        one.Produce();

        string value = queueArray[0].Dequeue(); //this line sets "one" to value
    }
}
于 2009-11-04T03:14:39.347 に答える
0

単に次のことを行ってみませんか。

public void Produce()
{
    _queue.Clear();
    _queue.Enqueue("one");
}
于 2012-02-03T20:25:02.940 に答える
-1

この種の問題の一般的なアプローチ....デバッガーを使用してコードをステップ実行し、例外がスローされる原因となる行を確認します。

于 2009-11-04T02:20:55.440 に答える