使用ref关键字保存对象引用以供将来使用

时间:2011-09-06 21:02:50

标签: c# properties ref

说我有一个像这样的简单类:

public class ReferenceChanger<T> 
{
    public T SavedElement { get; private set; }

    public ReferenceChanger(T elementToSave)
    {
        SavedElement = elementToSave;
    }

    // This method would change the original variable (given as a constructor argument)
    public void SetNewReference(T newElement)
    {
        SavedElement = newElement;
    }
}

此类保存给定构造函数的元素,无论元素是什么。但是,“SavedElement”(其后备字段)是对实例创建时给定的对象的引用。

有没有办法保存引用变量(与使用ref关键字一样),这样如果传递给构造函数的原始项发生更改, SavedElement 会自动反映更改,几乎就像使用 ref 关键字传递对象一样? (即使我使用 ref 关键字,我也无法以这种方式保存引用。)

更新以使意图更清晰:

public class ExampleClass 
{
    public List<int> Numbers { get; set; }
}

public static void Main()
{
    ExampleClass temp = new ExampleClass();
    temp.Numbers = new List<int>() { 1, 2, 3 }; 

    ReferenceChanger<List<int>> changer = new ReferenceChanger<List<int>>(temp.Numbers);
    // Here, a reference to the List<int> instance (containing 1,2,3) is stored in changer's SavedElement

    // Then I do this:
    changer.SetNewReference(new List<int>() { 5, 6, 7 });

    // Now, only changer's SavedElement was changed, but temp's property Numbers was not changed.
    // Is there a way to change the temp's property Numbers from the changer?
}

3 个答案:

答案 0 :(得分:4)

听起来您正在寻找TypedReference__makeref关键字。

警告:它们的记录很少,而且不在C#的标准化部分。

this question.

中有更多信息

答案 1 :(得分:0)

C#中的所有类都是引用对象,因此您编码的内容应更新SavedElement的值。但是,如果T是基本类型(例如,int,string等),则这不起作用,因为它们是按值设置的。您需要在T上设置约束以确保它是一个类。

答案 2 :(得分:0)

您通常无法捕获对变量的引用并将其存储为属性。一个hackish解决方案(并不是真的暗示这是一个好主意,我首先探索其他途径)是在一个闭包中捕获它并传递闭包。闭包捕获变量,而不是值。因此,可以在其他地方观察变量的变化。例如,给定

class Foo
{
    public int Baz { get; set; }
}

class Bar
{
    private Func<Foo> fooGetter;

    public Bar(Func<Foo> fooGetter)
    {
        this.fooGetter = fooGetter;
    }

    public void Do()
    {
        Console.WriteLine(fooGetter().Baz);
    }
}

你可以拥有

Foo foo = new Foo() { Baz = 1 };
Bar bar = new Bar(() => foo);
bar.Do();
foo = new Foo() { Baz = 2 };
bar.Do();

观察到对变量foo的更改,因为这是调用者包含在lambda中的内容。如果来电者只是说() => new Foo(),你(当然)不会观察到任何变化。