【问题标题】:C# - passing parameters by reference to constructor then using them from methodC# - 通过引用构造函数传递参数,然后从方法中使用它们
【发布时间】:2012-10-18 17:13:52
【问题描述】:

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

有没有办法让方法改变主程序中变量的值? 谢谢!

【问题讨论】:

标签: c# methods reference constructor parameter-passing


【解决方案1】:

此行为是由以下原因引起的:

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# Reference)

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      您最好在 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/en-us/library/ms173109.aspx 。 (Int32 是一个结构,而在你的情况下你可能需要一个类)

      【讨论】:

        【解决方案4】:

        您尝试执行的操作无法完成,因为它并非设计用于以这种方式使用。您必须将参数直接输入Work 方法,例如

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

        【讨论】:

        • 遗憾的是 C# 不支持保存作为引用传递的参数。
        猜你喜欢
        • 1970-01-01
        • 2011-09-28
        • 2012-03-19
        • 1970-01-01
        • 2016-03-20
        • 1970-01-01
        • 2019-11-27
        • 2012-07-05
        相关资源
        最近更新 更多