В качестве пояснения, возьмите этот тип значения в 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;
не достигает результата, поскольку приведение распаковывает left
, и вы в конечном итоге изменяете копию. Так что, по крайней мере, в прямом C # это не похоже на то, что конструкция возможна.
Кто-нибудь знает, можно ли построить конструкцию с использованием отражения, небезопасного кода, dynamic
, кода IL или любым другим способом? Или кто-нибудь может показать, что CLR эффективно предотвращает такой контрольный цикл?
Обратите внимание, что я на самом деле не хочу создавать такой граф объектов. Скорее ответ может повлиять на разработку алгоритмов, которые работают с графами объектов, таких как форматеры сериализации / десериализации.
EDIT
Как предположил Брайан , действительно можно изменить упакованное значение, не распаковывая его, приведя его к типу интерфейса вместо типа значения. Итак, учитывая этот код:
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, почему изменяемые типы значений являются злом.