【问题标题】:C# and storing reference to method parameterC# 和存储对方法参数的引用
【发布时间】:2009-10-27 21:15:42
【问题描述】:

对于一些背景信息,我有一个在循环中运行的应用程序,并且在任何时候它都会调用 Tick 方法。有一堆类扩展了一个基类并且都有自己的tick方法,并被添加到依赖链中,这样当类A被调用并且它的链中有B和C的实例时,B.Tick被调用,然后是 C.Tick,最后是 A.Tick。

所以在伪代码中,我的类看起来像这样:

public class A : Super
Super b;
Super c;
ArrayList one;
ArrayList two;

tick(){
    one.Add(b.LastValue);
    two.Add(c.LastValue);
            ... do something with one and two ...
}

A(){
    b = new B(some other array list);
    c = new C(ref one);
}

B 工作正常,并且始终获得正确的值。问题是我猜你不能在一个类中存储对另一个变量的引用,所以当我做 new C(ref one);并且 C 的构造函数将一个类变量设置为一个,稍后在 A 中更新一个之后,就像 C 不再知道它仍然应该指向一个(现在已更新)并且只是空的(就像它最初一样在构造函数内部)。关于如何实现我想要做的事情,而不必使用 C# 指针和不安全代码的任何想法?谢谢,希望它有意义:)

编辑: 显然人们无法用与实际问题完全无关的令人困惑的伪代码来回答问题,因此更改为:

编辑 2:C 类

...
ArrayList local;
...
C(ref ArrayList one){
    local = one;
}

Tick(){
   LastValue = local[0] + 5; //not actual formula, just shows trying to use a referenced variable 
}

【问题讨论】:

  • 这是 c# 还是 Java?它被标记为 c#,但它确实看起来像 java。
  • 当你说“一个在A中更新”时,你是指tick类中的.Add还是其他一些更新?
  • 我认为“伪代码”类似于 Java,但他们想要 C# 解决方案
  • @joel,C# @Mikael,我的意思是 .Add @Richard,正确
  • extends 是一个 Java 关键字。 C# 使用冒号表示继承以及接口实现。

标签: c# pass-by-reference


【解决方案1】:

由于one 是一个ArrayList,您可以将其作为引用传递。您现在显然将它作为对构造函数的引用传递。你可能不需要那个ref

但请更全面地说明您要完成的工作。

编辑:

看过你的 C 课后,就不需要ref了。 c 将共享 A 调用 one 的 ArrayList 的实例。

这似乎归结为 .NET 中的一般引用类型/值类型问题。总结一下:

  • 对象的实例没有名称,并且根本不能(物理上)作为参数传递。
  • 您总是通过引用访问实例。在您的代码中,one (2x) 、twolocal 都是对 Arraylist 实例的引用。
  • 引用本身的行为类似于值类型,即赋值意味着复制。

要了解有关引用类型/值类型的更多信息,请搜索“复制语义”并避免以“堆栈上存在值类型”开头的帖子。

【讨论】:

  • “既然一个是ArrayList,你只能作为引用传递”应该替换为“因为一个是ArrayList,你只能传递它的引用”,因为你实际上并没有传递“它”作为任何东西。您正在按值传递它的引用(或者如果它的 ref 则通过引用)。
  • Mehrdad,字面上是正确的,但我倾向于酌情缩短“按值传递它的引用”。
  • 换句话说(如果我可以的话):用ref 传递它为方法体提供了一种更改调用变量指向的实际对象的方法。不将其作为ref 传递并为参数分配不同的对象,不会损害传递的变量。这与更改传递的对象的成员不同,因为双方都指向同一个对象。
【解决方案2】:

没有什么可以阻止您这样做。不过,这是否是一个好主意是另一个问题。一般来说,如果可以避免,我建议尽量避免在方法调用之间更改状态。当然,关键的表达是“如果你能避免它”。 :-)

【讨论】:

    【解决方案3】:

    你不能在一个类中存储对另一个变量的引用

    你可以,人们一直都在这样做。只需将其分配给(私有)字段。

    所以当我做 new C(ref one); [snip /] 稍后在 A 中更新一个之后,就像 C 不再知道它仍然应该指向一个

    实际上,它确实知道,但您应该将one 分配给成员字段。分配给对象只不过是设置对对象的引用。更改对象,在您分配它的任何地方更改它们:

    class A
    {
        public string Hello { get; set; }
    }
    
    class C
    {
        private A myA;
        public C(A a) { myA = a; }
        public A GetMyA() { return myA; }
    }
    
    // somewhere else:
    A someA = new A();
    someA.Hello = "Hello World";
    C someC = new C(someA);
    someA.Hello = "Other World";
    Console.WriteLine(someC.GetMyA().Hello);
    
    // this will print "Other World" and not "Hello World" as you suggest
    

    PS:既然你发布了伪代码,我希望你不介意我把它简化一下。如果我误解了您的问题,请忽略(如果可能,请澄清一下)。

    PPS:重新阅读您的(编辑的)代码并仍然试图找出问题所在,似乎没有什么可以阻止您的代码中的 C 保留引用 A 的成员和调用a.Add 显然也会反映c 中的成员变量。确实,这里不需要ref

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-13
      • 2013-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多