简体   繁体   English

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

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

In the following code, I am trying to have a method(Work) from class TestClass change the values of some variables in the main program without having to return them. 在下面的代码中,我试图让TestClass类的method(Work)更改主程序中某些变量的值,而不必返回它们。 The variables are passed by reference in the TestClass constructor. 变量在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);
    }
}

However this code returns : 但是,此代码返回:

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

Is there any way to have the method change the values of the variables in the Main program? 有什么方法可以让该方法在主程序中更改变量的值? Thank you! 谢谢!

Not possible. 不可能。 You can't store a reference to an int as a member, and just int a is a copy - changes to the copy don't change the original, as you've seen. 您不能将对int的引用存储为成员,而仅仅是int a是副本-如您所见,对副本的更改不会更改原始副本。

You could wrap that int inside a class. 您可以将该int包装在类中。 You can store a reference to the class and operate on it then. 您可以存储对该类的引用,然后对其进行操作。

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);
    }
}

You would be better off creating your own wrappers over Int32 in order for changes to be reflected, because once the values are assigned to fields of the class, they are no longer references, but rather different instances of Int32. 您最好在Int32上创建自己的包装程序以反映更改,因为一旦将值分配给该类的字段,它们就不再是引用,而是Int32的不同实例。 Consider the following code: 考虑以下代码:

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;
    }
}

So now you have an Integer -- a wrapper class over Int32. 所以现在您有了一个Integer-Int32上的包装器类。 The usage will bring you the results: 用法将为您带来结果:

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);

The output is: 输出为:

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

You may also find it useful to read more about classes and structs in C#, eg http://msdn.microsoft.com/en-us/library/ms173109.aspx . 您可能还会发现,阅读有关C#中的类和结构的更多信息很有用,例如http://msdn.microsoft.com/zh-cn/library/ms173109.aspx (Int32 is a struct, whereas in your case you probably need a class) (Int32是一个结构,而您可能需要一个类)

What you are trying to do can't be done as it wasn't designed to be used in that way. 您尝试做的事情无法完成,因为它不是设计用于这种方式的。 You would have to have the parameters going into the Work method directly instead eg 您必须直接将参数输入Work方法中,例如

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

This behaviour is caused by: 这种现象是由以下原因引起的

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 is a structure (a value type). int是一种结构(值类型)。 This means that you're NOT passing the reference (or pointer) to the fields as you may expect, even if you use the ref keyword. 这意味着即使您使用ref关键字,也不会像您期望的那样将引用(或指针)传递给字段。 What you're doing instead is assigning to the fields the integer values given as input, nothing more. 相反,您正在做的就是为字段分配作为输入给出的整数值,仅此而已。
To achieve what you're expecting you have to use a reference type (wrap your integer into a class) or reference your integers (through the ref keyword) in the method where you actually change their values: 为了达到您的期望,您必须在实际更改其值的方法中使用引用类型(将整数包装到类中)或引用整数(通过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);
}

The effect of passing by reference is that any change to the parameter in the called method is reflected in the calling method. 通过引用传递的效果是,被调用方法中参数的任何更改都会反映在调用方法中。

To understand more about the ref keyword give a look to: ref (C# Reference) . 要了解有关ref关键字的更多信息,请看一下: ref(C#参考)

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

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