powered by simpleCommunicator - 2.0.57     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / вызов вирт метода в конструкторе - как избежать
16 сообщений из 16, страница 1 из 1
вызов вирт метода в конструкторе - как избежать
    #38183479
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть базовый класс Base. В нем есть метод(виртуальный) который что-то парсит и делает из этого объект MyObject, вызываю метод в конструкторе. Почему он виртуальный? Т.к. наследник может изменить логику парсинга. Объект MyObject доступен для чтения потомкам (public get;).
Как избавить от виртуальности, но при этом не вызывая этот метод отдельно? Пока такие варианты:
1. передавать объект MyObject в конструктор, если он null вызывать метод (но уже приватный)
2. передавать делегат парсинга, что вообщем не сильно от п.1 отличается...
Какие предложения?
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183534
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ничего не понял. Так?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
public class MyObject
{
    // ...
}

public class Base
{
    private MyObject myObject;

    public MyObject MyObject
    {
        get { return myObject; }
    }

    public Base()
    {
        DoParse();
    }

    private void DoParse()
    {
        myObject = Parse();
    }

    protected virtual MyObject Parse()
    {
        return new MyObject();
    }
}
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183545
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA,

хм, ну да
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183546
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivan, и что не устраивает?
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183556
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA,

да вроде уже все. я дурак просто)
делал примерно так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  public Base()
    {
       myObject = Parse();
    }

 
    protected virtual MyObject Parse()
    {
        return new MyObject();
    }
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183672
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вызов виртуального метода в конструкторе - плохая практика, чреватая исключениями в случае, если текущий экземпляр не является most derived потомком базового класса в иерархии наследования - virtual member будет всегда вызываться именно для этого most derived, конструктор которого еще не отработал.
Решарпер, выдавая warning на virtual member constructor call, в т.ч. просто предлагает сделать класс sealed. Здесь, как я понимаю, наследование нужно. Я бы смотрел в сторону паттернов типа FactoryMethod.
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183795
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,

с трудом представляю где тут фабрику воткнуть...
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183910
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivan,

Тут просто надо себе хорошо представлять, чем может быть чреват вызов виртуального метода в конструкторе - он в ряде случаев вполне возможен, и ничем не чреват:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
public class Class1
{
  public Class1()
  {
    Console.WriteLine("Class1.ctor");
    DoSome();
  }
  public virtual void DoSome()
  {
    Console.WriteLine("Class1.DoSome");
  }
}

public class Class2 : Class1
{
  public Class2()
  {
    Console.WriteLine("Class2.ctor");
    DoSome();
  }
  public override void DoSome()
  {
    Console.WriteLine("Class2.DoSome");
  }
}

public class Class3 : Class2
{
  public Class3()
  {
    Console.WriteLine("Class3.ctor");
    DoSome();
  }
  public override void DoSome()
  {
    Console.WriteLine("Class3.DoSome");
  }
}


Вызываем:
Код: c#
1.
new Class3();


В консоли получаем:

Код: plaintext
1.
2.
3.
4.
5.
6.
Class1.ctor
Class3.DoSome
Class2.ctor
Class3.DoSome
Class3.ctor
Class3.DoSome

Теперь меняем Class3 вот так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public class Class3 : Class2
{
  private readonly int _a;
  public Class3()
  {
    _a=2;
    Console.WriteLine("Class3.ctor");
    DoSome();
  }
  public override void DoSome()
  {
    Console.WriteLine("Class3.DoSome: {0}", 10/_a);
  }
}


Вызываем, и после вывода Class1.ctor сразу получаем DivideByZeroException. Причина - в конструкторе Class1 был вызван виртуальный метод most derived реализации, т.е. от Class3, но при этом еще не был вызван конструктор Class3, который нужным образом инициализирует состояние. Т.е. если реализация виртуального метода не зависит от состояния most derived класса, то вызов этого метода в конструкторе ничем не чреват. Только вот если потом кто-то унаследуется от такого класса, и реализует метод с завязкой на состояние - то может быть по-разному.
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183911
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivan, не обязательно фабрику втыкать. Вот:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
public class Base
{
    private MyObject myObject;

    public MyObject MyObject
    {
        get { return myObject; }
    }

    protected Base()
    {
        // ...
    }

    protected void DoParse()
    {
        myObject = Parse();
    }

    protected virtual MyObject Parse()
    {
        return new MyObject();
    }
}

public class Derived : Base
{
    public static Derived Create()
    {
        var instance = new Derived();

        instance.DoParse();

        return instance;
    }

    private Derived()
    {
        // ...
    }
}
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38183933
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,

спасибо за пример. состояние у меня на данный момент нет, т.е. все просто - на вход строка, на выходе объект. Разница в классах(базовый и наследники) только в алгоритме. Но это я так думаю сейчас, но как вы правильно заметили, кто знает что сделают последователи :)

skyANA,

спасибо,рассмотрим.
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38184747
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivan,

разделть конструирование и окончательную инициализацию - религия не позволяет?
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38185380
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

я так понимаю это:
Код: c#
1.
2.
[src]Class c = new Class();
c.InitBlablA();

[/SRC]
конечно такой вариант есть, только это метод надо отдельно вызывать и писать проверки. такой вариант конечно имеет место быть)
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38185414
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanтолько это метод надо отдельно вызывать и писать проверки. такой вариант конечно имеет место быть)
ну а если статик метод?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
public class Base
{
    public static Base MakeBase()
    {
          Base B=new Base();
          B.DoParse(); // <= оно видно , не смотря на private DoParse
          if (good)   return B;
          else return null;
    }
    //или protected 
    private Base()
    {   //.......
    }
    private void DoParse()
    {  //.......
    }
}
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38185506
Фотография skyANA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beg-in-ernetivanтолько это метод надо отдельно вызывать и писать проверки. такой вариант конечно имеет место быть)
ну а если статик метод?Предлагал уже: 14047768 . ТС написал, что рассмотрят.
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38185556
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA,

nj
...
Рейтинг: 0 / 0
вызов вирт метода в конструкторе - как избежать
    #38185557
beg-in-er
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skyANA,
что это было, сорвалось )) , не заметил статик предложение.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / вызов вирт метода в конструкторе - как избежать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]