可以"参考"用作类之间的持久链接?

时间:2014-03-28 10:41:01

标签: c# .net mono

我有一个ClassA实例作为引用传递给ClassB的构造函数。现在,ClassB的实例是否始终可以访问传递的ClassA实例的最新更新版本?

public class ClassA {
    private int variableA = 0;
    public ClassA() { }
    public void Change(int newValue) {
        variableA = newValue;
    }
}

public class ClassB {
    public ClassA classA;
    public ClassB(ref ClassA refClassA) {
        classA = refClassA;
    }
    public void Print() {
        Console.WriteLine(classA.variableA);
    }
}

static void Main() {
    ClassA classA = new ClassA();
    ClassB classB = new ClassB(ref classA);
    classB.Print(); // 0
    classA.Change(50);
    classB.Print(); // 50?
}

我已经阅读了我在互联网上找到的内容,但我发现的唯一用途是更新引用的值,例如dotnetperls http://www.dotnetperls.com/ref

6 个答案:

答案 0 :(得分:1)

这不是ref的用途,没有它就可以实现相同的行为。

答案 1 :(得分:1)

这里不需要ref关键字。即使没有它,ClassB也会持有对ClassA的引用,而不是其值的副本。

请注意,由于variableA是私有的,因此您的代码将无效,因此ClassB无法在其Print方法中访问它。除此之外,输出将如您在示例中所预期的那样

答案 2 :(得分:1)

ref与持久性无关。它只表示您可以更改原始变量的值。如果你调用一个没有ref的方法,该方法可以根据需要分配该变量,并且调用者的变量不会改变。使用ref,来电者也会指向另一个地方。

简单示例:

void Call(int x)
{
  x = 2;
}

void CallRef(ref int x)
{
  x = 10;
}

int a=0;
Call(a); // a is still 0
CallRef(ref a); // a is 10

答案 3 :(得分:1)

是的。但它甚至不需要,因为对象总是指针,ref关键字用于将非对象的指针传递给函数(例如:int,float,structs等)。

答案 4 :(得分:0)

是的,它有参考。这意味着它不保存ClassA元素的值,而只保存它在内存中(堆上)的地址。

因此,请确保不要重新实例化classA:

classA.change(50)可以使用,但classA = new ClassA()不会。

另外,请注意引用类型(例如类)不需要ref关键字,它们会以这种方式自动处理。

答案 5 :(得分:0)

如果您想要访问ClassA的最后一个实例,可以用这样的类包装变量:

public class Ref<T>
{
    readonly Func<T> getter;
    readonly Action<T> setter;

    public T Value
    {
        get
        {
            return getter();
        }
        set
        {
            setter(value);
        }
    }

    public Ref(Func<T> getter, Action<T> setter)
    {
        this.getter = getter;
        this.setter = setter;
    }
}

然后像这样修改你的ClassB

public class ClassB
{
    readonly Ref<ClassA> refClassA;

    public ClassA ClassA
    {
        get
        {
            return refClassA.Value;
        }
    }

    public ClassB(Ref<ClassA> refClassA)
    {
        this.refClassA = refClassA;
    }

    public void Print()
    {
        Console.WriteLine(ClassA.VariableA);
    }
}

然后你可以测试并看看你是否有所需的行为:

var a = new ClassA(1);
var b = new ClassB2(new Ref<ClassA>(() => a, x => a = x));

b.Print(); // output 1

var c = a; // backup old reference

a = new ClassA(2);

b.Print(); // output 2

// b stores old instance of a?
Console.WriteLine(object.ReferenceEquals(b.ClassA, c)); // output false
// a stores new instance of a?
Console.WriteLine(object.ReferenceEquals(b.ClassA, a)); // output true

我认为你会这样做,请记住这是一个草稿,所以你必须做很多工作。

修改

我从Eric Lippert的博客中偷了Ref<T>课,最后我发现了SO question他发布的帖子。