В качестве объяснения возьмем этот тип значения в C #:
struct ObjRef
{
public object Value;
public ObjRef(object value) { Value = value; }
}
Я могу представить граф объектов, где есть два экземпляра в штучной упаковке этого типа, каждый из которых ссылается на другой. Это то, что я имею в виду под циклом ссылок только с типами-значениями.
Мой вопрос в том, можно ли когда-либо построить такой граф объектов в .NET. Концептуально конструкция, если она существует, выглядела бы так:
object left = new ObjRef();
object right = new ObjRef(left);
left.Value = right;
, но очевидно, что последняя строка не является допустимым C #. Создание последней строки:
((ObjRef)left).Value = right;
не дает результата, так как приведение распаковывает слева
, и вы в конечном итоге мутируете копию. Так что, по крайней мере, в C #, это не похоже на то, что конструкция возможна.
Кто-нибудь знает, можно ли построить конструкцию с помощью отражения, небезопасного кода, динамический
, код IL или любым другим способом? Или может кто-нибудь показать, что CLR эффективно предотвращает такой цикл ссылок?
Обратите внимание, что я на самом деле не хочу создавать такой граф объектов. Скорее, ответ может повлиять на разработку алгоритмов, которые работают с графами объектов, таких как средства форматирования сериализации / десериализации.
РЕДАКТИРОВАТЬ
Как Брайан предположил, действительно можно изменить упакованное значение без распаковав его, приведя к типу интерфейса вместо типа значения. Итак, учитывая этот код:
interface IObjRef
{
IObjRef Value { get; set; }
}
struct ObjRef : IObjRef
{
IObjRef value;
public IObjRef Value { get { return value; } set { this.value = value; } }
public ObjRef(IObjRef value) { this.value = value; }
}
, тогда описываемый мной ссылочный цикл может быть построен следующим образом:
IObjRef left = new ObjRef();
IObjRef right = new ObjRef(left);
left.Value = right;
Что в основном оставляет нам причину №72, почему изменяемые типы значений - зло.