Забавное свойство .НЕТ ООП модели

bleyman



using System;
namespace ZZZZ
{
public class A
{
public A(ref object zzz)
{
zzz = this;
}
}
public class B : A
{
public B(ref object zzz) : base(ref zzz)
{
throw new Exception;
}
}
public class EntryPoint
{
public static void Main
{
object zzz = null;
B b = null;
try
{
b = new B(ref zzz);
}
catch
{
Console.WriteLine("Constructor failed, (b == null) is " + (b == null;
}
Console.WriteLine("zzz.ToString == " + zzz.ToString;
}
}
}


Так вот. Результат запуска - удивительный! b == null, а вот zzz указывает на типа работающий объект типа B. И этот объект, естественно, не собирается GC. И узнать изнутри объекта, что конструктор недоработал, имхо, никак.
И ето глюк даже плюсовой концепции ООП, насколько я понимаю.
Это я к тому, что мне не удалось сделать абстрактный класс, который себя добавлял бы в специальный список в конструкторе. Потому что если бы ебнулся конструктор унаследованного класса, то вышла бы хуйня. Вот.

mirt1971

Ну в с++ в таком случае обязан вызваться деструктор базового класса, который может все починить(в твоем случае удалить элемент из списка)

bleyman

О да! Сорри, в С++ все ок.
А вот в С# и жаве кажыся херня выходит. Потому что деструкторы не могут вызваться пока на объект есть сцылки. А они есть.

6yrop

пока на объект есть сцылки.

может не в тему, пример смотреть сейчас влом, в .Net есть обработка циклический ссылок

bleyman

Да, не в тему. Это ты верно подметил, что не в тему =)

Hastya

В Джаве нет передачи параметров по ссылке.

bleyman

И что с того? Я могу передать объект с паблик ссылкой на объект внутри. И вообще в оригинале хотелось чего-то такого:
class ObjectManager
{
... // hueta raznaja
internal void AddObject(object obj);
... // eshe hueta
}
И чтобы класс А был бы абстрактным и в той же либе, что и этот самый ObjectManager, и можно было бы писать
B b = new B(ObjectManager);
А не
B b;
ObjectManager.Add(b = new B;
Но подумав, я пришел к выводу, что эквилингамно на самом деле.

bastii

что-то я не понял,
в чем проблема?

bastii

разве там не все ок с виртуальными таблицами и с занесением в список объектов с файналяйз при необходимости?

bleyman

Проблема в том, что конструктор объекта может сработать не до конца. В том смысле, что конструктор базового класса сработал, а собственный - вылетел.
Если ты в конструкторе базового класса заныкал где-нить ссылку на this, то деструктор базового класса не вызовется (в отличие от плюсов) - потому что сцылка-то есть! И никакого явного способа узнать из базового класса что объект не инициализирован до конца не существует, насколько я понимаю.

bastii

ну раз ссылочку заныкал, значит так надо, поэтому и не разрушиться
ты ведь эксепшин ловишь, вот и очищай ссылочку

bastii

в НЕТе просто деструкторов нет

bastii

чем вообще если заменить ситуацию из примера с конструктором на метод, то что измениться
void m(ref object obj) {
obj = new A;
throw new Exception;
}
ну объект не очиститься, так ты сам так захотел

Hastya

тогда объект будет существовать, а почему ты решил, что нельзя определить, инициализировался он или нет?

bleyman


тогда объект будет существовать, а почему ты решил, что нельзя определить, инициализировался он или нет?

Изнутри нельзя. Блин, я же объяснил, что я хотел сделать. Типа некий объект ObjectManager и абстрактный класс ManagedObject и связать их максимально независимо от программера, который будет наследоваться от ManagedObject. Мне не удалось сделать это так как я хотел. Потому что нельзя определить, инициализировался объект до конца или нет. В том смысле, что получается ситуация, когда единственная ссылка на этот объект есть у ObjectManager.
Забейте, короче. Все хорошо.

Hastya

public MyObject {
initialize;
initialized = true;
}

bleyman

эээ. Я ж сказал - из основы иерархии, т.е. базового абстрактного класса ManagedObject контролировать! Можно, конечно, обязать программера в начале каждого унаследованного конструктора выставлять initialized = false; а в конце - обратно, но это уж точно песдетс!

Hastya

контролировать инициализацию дочерних классов?
тогда тебе не конструктор нужен, а что вроде abstract virtual initialize

rosali

Есть в .NET такая штука, называется WeakReference. Если в Manager-е ты будешь ссылаться на объекты не по обычной ссылке, а по этой самой слабой ссылке, то GC будет собирать их в мусор, когда сильных (=обычных) ссылок не останется. ВОТ!

bleyman

Я об этом думал.
Но фишка в том, что предназначение манагера - как раз хранить сцылки, чтобы можно было сделать fire-and-forget.
Но не хотелось бы иметь дохлые (т.е. недоинициализированные) объекты.
хз, короче.
Оставить комментарий
Имя или ник:
Комментарий: