2010-03-29 130 views
8

你会如何分享两个其他对象之间的同一个对象?例如,我喜欢这种风格的东西:如何在两个类之间共享一个变量?

class A 
{ 
    private string foo_; // It could be any other class/struct too (Vector3, Matrix...) 

    public A (string shared) 
    { 
     this.foo_ = shared; 
    } 

    public void Bar() 
    { 
     this.foo_ = "changed"; 
    } 
} 

... 
// inside main 
string str = "test"; 
A a = new A(str); 

Console.WriteLine(str); // "test" 
a.Bar(); 
Console.WriteLine(str); // I get "test" instead of "changed"... :(

在这里,我不想给予一个酒吧方法。我想实现的东西,看起来像在C++:

class A 
{ 
    int* i; 
public: 
    A(int* val); 
}; 

A::A (int* val) 
{ 
    this->i = val; 
} 

我看有一些REF /出的东西,但我不能让我问这里。我只能在我使用ref/out参数的方法范围中应用一些更改... 我也读过我们可以使用指针,但是没有其他方法可以使用它吗?

+0

在你的例子中,字符串不是一个很好的例子,因为它们是不可变的。 – Ikaso 2010-03-29 04:49:01

回答

9

这与共享对象无关。您将一个字符串引用传递给A构造函数。该参考被复制到私人会员foo_中。稍后,您调用B(),将foo_更改为“已更改”。

您从未修改strstrmain中的局部变量。你从未传过对它的引用。我会分裂

C myC = new C() {Property = 1;} 
A myA = new A(myC); 
B myB = new B(myC); 

int i1 = myC.Property; // 1 
myA.ChangeC(2); 
int i2 = myC.Property; // 2 
myB.ChangeC(3); 
int i3 = myC.Property; // 3 
+0

事实上,它会应付这里像你的建议那样做,但这不是我想要做的。在这里,我真的希望我的类A和B通过将它提供给A和B构造函数来处理同一个对象。然后,他们将自己在共享对象上工作,而不必在每个方法调用都有一个ref参数(我想让我的Bar方法不带参数)。例如:一个跟随其对象的Oriented Bounding Box。如果我可以分享OBB和对象之间的位置,那么每次对象移动时我都不必更新OBB位置。 – Altefquatre 2010-03-29 05:06:27

+1

然后只是将对象传递给两个构造函数。这不是你在你的例子中所做的。另外,传递一个字符串将不起作用,因为字符串是不可变的。 – 2010-03-29 05:10:10

+0

好吧我得到它的类。但是如果C是一个结构体,那么这个代码就不能工作了......你会如何解决这个问题? (例如,它将传递Vector3,它是struct ...) – Altefquatre 2010-03-29 05:39:03

2

如果你曾经想改变str,你可以这样来定义B中

public void Bar(ref string s) 
    { 
    this.foo_ = "changed"; 
    s = this.foo_; 
    } 

考虑:

public class C 
{ 
    public int Property {get;set;} 
} 

public class A 
{ 
    private C _c; 
    public A(C c){_c = c;} 

    public void ChangeC(int n) {_c.Property = n;} 
} 

public class B 
{ 
    private C _c; 
    public B(C c){_c = c;} 

    public void ChangeC(int n) {_c.Property = n;} 
} 

我对2部分的回答: 1)如果这个变量是一个引用类型,那么它将它的引用传递给所有感兴趣的对象之后,它就已经被共享了。唯一需要注意的是引用类型实例是可变的。 2)如果变量是一个值类型比你不得不使用ref或out或者一些可变的包装器,你可以使用方法或属性来改变包装器中的值。 希望有所帮助。

5

将你的字符串包装在一个类中。你需要这样做,因为字符串是不可变的。任何尝试更改字符串实际上都会产生一个新字符串。

class Foo { 
    class StringHolder { 
     public string Value { get; set; } 
    } 
    private StringHolder holder = new StringHolder(); 
    public string Value { 
     get { return holder.Value; } 
     set { holder.Value = value; } 
    } 
    public Foo() { } 
    // this constructor creates a "linked" Foo 
    public Foo(Foo other) { this.holder = other.holder; } 
} 

// .. later ... 

Foo a = new Foo { Value = "moose" }; 
Foo b = new Foo(a); // link b to a 
b.Value = "elk"; 
// now a.Value also == "elk" 
a.Value = "deer"; 
// now b.Value also == "deer" 
+0

+1我可能会把'StringHolder'作为一个私有的嵌套类。 – fre0n 2010-03-29 05:00:43

+0

不是一个坏主意:) – Jimmy 2010-03-29 05:07:21

2

您需要通过放慢参数为你的方法的引用,

class A 
     { 
      private string foo_; // It could be any other class/struct too (Vector3, Matrix...) 

      public A(string shared) 
      { 
       this.foo_ = shared; 
      } 

      public void Bar(ref string myString) 
      { 
       myString = "changed"; 
      } 
     } 

static void Main() 
     { 
      string str = "test"; 
      A a = new A(str); 

      Console.WriteLine(str); // "test" 
      a.Bar(ref str); 
      Console.WriteLine(str); 

     } 
相关问题