繁体   English   中英

C#-通过引用构造函数传递参数,然后从方法中使用它们

[英]C# - passing parameters by reference to constructor then using them from method

在下面的代码中,我试图让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

有什么方法可以让该方法在主程序中更改变量的值? 谢谢!

不可能。 您不能将对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);
    }
}

您最好在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;
    }
}

所以现在您有了一个Integer-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/zh-cn/library/ms173109.aspx (Int32是一个结构,而您可能需要一个类)

您尝试做的事情无法完成,因为它不是设计用于这种方式的。 您必须直接将参数输入Work方法中,例如

testObj.Work(ref a, ref b, ref c, ref d);

这种现象是由以下原因引起的

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#参考)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM