【问题标题】:Save a object reference for future usage using ref keyword使用 ref 关键字保存对象引用以供将来使用
【发布时间】:2011-09-06 21:02:49
【问题描述】:

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

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;
    }
}

无论 element 是什么,这个类都会保存一个给定其构造函数的元素。但是,“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?
}

【问题讨论】:

  • 看到类是自动引用类型,传递给你的ctor的对象的变化应该反映在你的SavedElement中,因为它只是引用该对象,它不是通过值传递,而是通过引用传递。
  • 您的意思是说您希望在调用SetNewReference 之前消耗了SavedElement 值的代码随后对新版本的SavedElement 执行操作?
  • 如果是这样,只需将整个 ReferenceChanger 实例传递给操作并让它在需要时调用 SavedElement。它将始终使用“最新”参考。
  • @Tony 我想你误解了我的问题。我将添加更多描述它的代码。被引用对象的更改将可见,但其变量中的对象更改不可见。
  • 评论者没有抓住问题的重点。 1) T 不限于引用类型。 2) 他想捕获对 variable 的引用(他不能这样做,为了记录),以便当 variable 更改时,他会看到它。 @Kornelije,如果您可以确认要观察变量的变化,而不仅仅是变量的原始对象,那可能会有所帮助。或者也许我是那个漏掉了重点的人,你也可以确认一下。

标签: c# properties ref


【解决方案1】:

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

警告:它们的文档记录很差,并且不在 C# 的标准化部分中。

this question.有更多信息

【讨论】:

    【解决方案2】:

    C# 中的所有类都是引用对象,因此您编写的代码应该更新SavedElement 的值。但是,如果T 是原始类型(例如,int、string 等),则这将不起作用,因为它们是按值设置的。您需要对 T 施加约束以确保它是一个类。

    【讨论】:

    • 稍作修正 - 字符串是引用类型,它恰好是不可变引用类型。您可以有两个字符串变量指向完全相同的字符串实例。
    【解决方案3】:

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

    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 中的内容。如果来电者只是说() =&gt; new Foo(),您(当然)不会观察到任何变化。

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 1970-01-01
      • 2011-11-07
      • 2017-02-11
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      相关资源
      最近更新 更多