Сохраните ссылку на объект для будущего использования, используя ключевое слово ref - PullRequest
3 голосов
/ 07 сентября 2011

Скажем, у меня есть простой класс, подобный этому:

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

Ответы [ 3 ]

4 голосов
/ 07 сентября 2011

Звучит так, будто вы ищете TypedReference и ключевое слово __makeref.

Предупреждение: они плохо документированы и не входят в стандартную часть C #.много больше информации в этот вопрос.

0 голосов
/ 07 сентября 2011

Обычно вы не можете захватить ссылку на переменную и сохранить ее как свойство. Одно из хакерских решений (на самом деле не предполагая, что это хорошая идея, я бы сначала изучил другие пути) - это зафиксировать его в закрытии и передать закрытие вокруг. Замыкания захватывают переменные, а не значения. В результате изменения переменных можно наблюдать в другом месте. Например, учитывая

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, так как это то, что вызывающая сторона заключает в лямбду. Если бы абонент просто сказал () => new Foo(), вы бы (конечно) не заметили никаких изменений.

0 голосов
/ 07 сентября 2011

Все классы в C # являются ссылочными объектами, поэтому то, что вы кодировали, должно обновить значение SavedElement.Однако, если T является примитивным типом (например, int, string и т. Д.), Это не будет работать, поскольку они устанавливаются по значению.Вам нужно будет наложить ограничение на T, чтобы убедиться, что это класс.

...