13

次のコードでは、クラスTestClassのmethod(Work)に、メインプログラムの一部の変数の値を返さずに変更させようとしています。変数は、TestClassコンストラクターで参照によって渡されます。

class Program
{
    static void Main(string[] args)
    {
        int a, b, c, d;
        a = 5; b = 10; c = 20; d = 25;
        Console.WriteLine("Main before TestClass: a=" + a + " b=" + b + " c=" + c + " d=" + d);
        TestClass testObj = new TestClass(ref a,ref b,ref c,ref d);
        testObj.Work();
        Console.WriteLine("Main after TestClass: a=" + a + " b=" + b + " c=" + c + " d=" + d);
        Console.ReadLine();
    }
}

public class TestClass
{
    int _a, _b, _c, _d;
    public TestClass(ref int a, ref int b, ref int c, ref int d)
    {
        _a = a; _b = b; _c = c; _d = d;
    }

    public void Work()
    {
        Console.WriteLine("Work before changing: a=" + _a + " b=" + _b + " c=" + _c + " d=" + _d);
        _a = 0; _b = 1; _c = 2; _d = 3;
        Console.WriteLine("Work after changing: a=" + _a + " b=" + _b + " c=" + _c + " d=" + _d);
    }
}

ただし、このコードは次を返します。

Main before TestClass: a=5 b=10 c=20 d=25
Work before changing: a=5 b=10 c=20 d=25
Work after changing: a=0 b=1 c=2 d=3
Main after TestClass: a=5 b=10 c=20 d=25

メソッドにメインプログラムの変数の値を変更させる方法はありますか?ありがとうございました!

4

4 に答える 4

4

ありえない。intへの参照をメンバーとして保存することはできません。これint aは単なるコピーです。これまで見てきたように、コピーを変更しても元のファイルは変更されません。

intそれをクラス内でラップすることができます。クラスへの参照を保存して、それを操作できます。

public class IntWrapper
{
    public IntWrapper( int val = 0 ) { Value = val; }
    public int Value { get; set; }
}

static void Main(string[] args)
{
    IntWrapper a = new IntWrapper(5);
    TestClass testObj = new TestClass(a);
    testObj.Work();
}

public class TestClass
{
    IntWrapper _a;
    public TestClass(IntWrapper a)
    {
        _a = a;
    }

    public void Work()
    {
        Console.WriteLine("Work before changing: a=" + _a.Value);
        _a.Value = 0;
        Console.WriteLine("Work after changing: a=" + _a.Value);
    }
}
于 2012-10-29T11:39:53.203 に答える
4

変更が反映されるように、Int32上に独自のラッパーを作成することをお勧めします。これは、値がクラスのフィールドに割り当てられると、それらは参照ではなく、Int32の異なるインスタンスになるためです。次のコードを検討してください。

class Integer {
    public int Value;

    public Integer(int value) {
        Value = value;
    }

    public override string ToString() {
        return Value.ToString();
    }
}

class TestClass {
    Integer _a, _b, _c, _d;

    public TestClass(Integer a, Integer b, Integer c, Integer d) {
        _a = a;
        _b = b;
        _c = c;
        _d = d;
    }

    public void Work() {
        _a.Value = 111;
        _b.Value = 222;
        _c.Value = 333;
        _d.Value = 444;
    }
}

これで、整数(Int32のラッパークラス)ができました。使用法はあなたに結果をもたらすでしょう:

Integer a = new Integer(0), b = new Integer(0), c = new Integer(0), d = new Integer(0);
Console.WriteLine("a: {0}, b: {1}, c: {2}, d: {3}", a, b, c, d);
new TestClass(a, b, c, d).Work();
Console.WriteLine("a: {0}, b: {1}, c: {2}, d: {3}", a, b, c, d);

出力は次のとおりです。

a: 0, b: 0, c: 0, d: 0
a: 111, b: 222, c: 333, d: 444

また、C#のクラスと構造体について詳しく読むと便利な場合があります(例: http: //msdn.microsoft.com/en-us/library/ms173109.aspx ) 。(Int32は構造体ですが、あなたの場合はおそらくクラスが必要です)

于 2012-10-29T11:44:54.060 に答える
2

そのように使用するように設計されていないため、あなたがやろうとしていることはできません。代わりに、パラメータをWorkメソッドに直接入力する必要があります。

testObj.Work(ref a, ref b, ref c, ref d);
于 2012-10-29T11:42:56.700 に答える
2

この動作の原因は次のとおりです。

int _a, _b, _c, _d;
public TestClass(ref int a, ref int b, ref int c, ref int d)
{
    _a = a; _b = b; _c = c; _d = d;
}

int構造体(値型)です。これは、refキーワードを使用している場合でも、期待どおりに参照(またはポインター)をフィールドに渡していないことを意味します。代わりに、入力として指定された整数値をフィールドに割り当てるだけです。
期待どおりの結果を得るには、実際に値を変更するメソッドで、参照型を使用する(整数をクラスにラップする)か、整数を参照する(refキーワードを使用)必要があります。

public void Work(ref int a, ref int b, ref int c, ref int d)
{
   Console.WriteLine("Work before changing: a=" + a + " b=" + b + " c=" + c + " d=" + _d);
   a = 0; b = 1; c = 2; d = 3;
   Console.WriteLine("Work after changing: a=" + a + " b=" + b + " c=" + c + " d=" + _d);
}

参照渡しの効果は、呼び出されたメソッドのパラメーターへの変更が呼び出し元のメソッドに反映されることです。

refキーワードの詳細については、ref(C#リファレンス)を参照してください。

于 2012-10-29T11:51:28.677 に答える