【问题标题】:Is there a way to store a reference to a reference of an object? [duplicate]有没有办法存储对对象引用的引用? [复制]
【发布时间】:2018-08-28 16:52:36
【问题描述】:
public class Program
{
    public static void Main()
    {
        Test[] tests = new Test[5];
        tests[0] = new Test(){Name = "A"};

        var consumer = new Consumer();
        consumer.test = tests[0];

        Console.WriteLine(consumer.test.Name);   //Prints A
        tests[0] = new Test(){Name = "B"};
        Console.WriteLine(consumer.test.Name);   //Would like this to point to new object and print B
    }
}

class Test
{
    public string Name {get; set;}
}

class Consumer
{
    public Test test {get; set;}
}

我想知道是否可以直接在 c# 中实现这种功能。换句话说,Consumer.test 是否有可能指向位于 tests[0] 中的任何 Test 实例,这样当数组元素值发生变化时,我仍然可以访问该新值。或者,换一种说法,是否可以持有对对象实例引用的引用?我知道一种解决方法是创建一个容器类来保存对 Test 对象的引用并传递它,但是我想知道是否可以直接这样做。

【问题讨论】:

  • 我首先要问你为什么要这样做?你想解决什么问题?您可能有一些方法可以解决这个问题,但它们可能带来的麻烦多于其价值。
  • 你可以将它包裹在另一个对象中,但我真的认为这是一个 X-Y 问题。
  • 你为什么不能再打电话给consumer.test = tests[0];?这将满足您的第二条评论。
  • 例如,您可以将Consumer.test 设为Func<Test> 而不是Test,但它可能会变得非常丑陋。
  • 不能直接做;您必须创建一个表示间接操作的类型。

标签: c#


【解决方案1】:

您可以通过创建自己的委托包装类来实现这一点

class MyRef<T> 
{
    private Func<T> getter;

    public MyRef(Func<T> getter)
    {
        this.getter = getter;
    }

    public T Value
    {
        get { return getter(); }
    }
}

将您的 Consumer 类修改为以下内容(添加构造函数并修改数据类型以利用委托包装器:

class Consumer
{
    public MyRef<Test> test { get; set; }

    public Consumer(MyRef<Test> t){
        test = t;   
    }
}

您在 Main 中的 Consumer 声明变为

var consumer = new Consumer(new MyRef<Test>(() => tests[0]));

您需要将来自消费者的调用更新为:

Console.WriteLine(consumer.test.Value.Name);

这是DotNetFiddle

【讨论】:

【解决方案2】:

我以前做过,但在有限场景中。在大多数情况下,我最终都会进行重构以避免额外的间接级别,因为这种需求通常是糟糕设计的症状。

您可以创建一个通用的Reference 类并持有对它的引用,而不是底层对象。如果您这样做,您可能希望将IReference 接口分发给“读取端”或消费者,并将IChangeReference 分发给“写入端”,以便可以操作引用的内容。

public interface IReference<T>
{
    T Value { get;
}

public interface IChangeReference<T>
{
    void SetValue(T value);
}

public class Reference<T>: IReference<T>, IChangeReference<T>
{
    public Reference(T value) => Value = value;

    public T Value { get; private set; }

    public void SetValue(T value) => Value = value;
}

public class SomeConsumer
{
    private IReference<string> someField;
    ...
}

【讨论】:

    猜你喜欢
    • 2017-11-10
    • 1970-01-01
    • 2023-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    相关资源
    最近更新 更多