Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / вызов вирт метода в конструкторе - как избежать / 16 сообщений из 16, страница 1 из 1
14.03.2013, 11:43
    #38183479
netivan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
есть базовый класс Base. В нем есть метод(виртуальный) который что-то парсит и делает из этого объект MyObject, вызываю метод в конструкторе. Почему он виртуальный? Т.к. наследник может изменить логику парсинга. Объект MyObject доступен для чтения потомкам (public get;).
Как избавить от виртуальности, но при этом не вызывая этот метод отдельно? Пока такие варианты:
1. передавать объект MyObject в конструктор, если он null вызывать метод (но уже приватный)
2. передавать делегат парсинга, что вообщем не сильно от п.1 отличается...
Какие предложения?
...
Рейтинг: 0 / 0
14.03.2013, 12:12
    #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
14.03.2013, 12:15
    #38183545
netivan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
skyANA,

хм, ну да
...
Рейтинг: 0 / 0
14.03.2013, 12:16
    #38183546
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
netivan, и что не устраивает?
...
Рейтинг: 0 / 0
14.03.2013, 12:21
    #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
14.03.2013, 13:02
    #38183672
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
Вызов виртуального метода в конструкторе - плохая практика, чреватая исключениями в случае, если текущий экземпляр не является most derived потомком базового класса в иерархии наследования - virtual member будет всегда вызываться именно для этого most derived, конструктор которого еще не отработал.
Решарпер, выдавая warning на virtual member constructor call, в т.ч. просто предлагает сделать класс sealed. Здесь, как я понимаю, наследование нужно. Я бы смотрел в сторону паттернов типа FactoryMethod.
...
Рейтинг: 0 / 0
14.03.2013, 13:43
    #38183795
netivan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
Сон Веры Павловны,

с трудом представляю где тут фабрику воткнуть...
...
Рейтинг: 0 / 0
14.03.2013, 14:29
    #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
14.03.2013, 14:29
    #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
14.03.2013, 14:38
    #38183933
netivan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
Сон Веры Павловны,

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

skyANA,

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

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

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

[/SRC]
конечно такой вариант есть, только это метод надо отдельно вызывать и писать проверки. такой вариант конечно имеет место быть)
...
Рейтинг: 0 / 0
15.03.2013, 12:29
    #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
15.03.2013, 13:13
    #38185506
skyANA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
beg-in-ernetivanтолько это метод надо отдельно вызывать и писать проверки. такой вариант конечно имеет место быть)
ну а если статик метод?Предлагал уже: 14047768 . ТС написал, что рассмотрят.
...
Рейтинг: 0 / 0
15.03.2013, 13:37
    #38185556
beg-in-er
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вызов вирт метода в конструкторе - как избежать
skyANA,

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


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