Разница в инициализации объекта внутри объявления класса v / s конструктор - PullRequest
0 голосов
/ 30 января 2019

Я проходил инициализацию объекта и инициализацию конструктора для моего объекта, но не смог получить точный ответ на мой вопрос.В чем здесь разница между делом 1 и делом 2;

дело 1:

namespace ConsoleApplication2
{
    class MyBuilder
    {
        private MySynchronizer m_synchronizer = new MySynchronizer();

        public MyBuilder()
        {

        }

        public void ProcessRecord(int recordNumber)
        {
            m_synchronizer.Process(recordNumber);
        }
    }
}

дело II:

namespace ConsoleApplication2
{
    class MyBuilder
    {
        private MySynchronizer m_synchronizer;

        public MyBuilder()
        {
          m_synchronizer = new MySynchronizer();

        }

        public void ProcessRecord(int recordNumber)
        {
            m_synchronizer.Process(recordNumber);
        }
    }
}

Это пример кода, показывающий, как я вызываю мой класс Builder;

 class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Press any key to stop");
            MyBuilder builder = new MyBuilder();
            builder.ProcessRecord(2);
        }
    }

[Извините, если я не смог бы правильно перефразировать вопрос, в этом случае любой может предоставить ссылку на другую статью SO]

Ответы [ 3 ]

0 голосов
/ 30 января 2019

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

Но, опять же, это только мое личное мнение.

0 голосов
/ 30 января 2019

Как уже упоминалось @Marc, разница в порядке базового конструктора.

Я добавил базовый конструктор

 class Base
    {
        public Base()
        {
            Console.WriteLine("Inside Base constructor");
        }
    }

и изменил мой класс "MyBuilder", чтобы он выводился из него как;

 class MyBuilder : Base
    {

    }

Теперь вывод из case1 выглядиткак:

enter image description here

, тогда как из case2:

enter image description here

Следовательно,

  • Если у вас есть несколько конструкторов, то подход case1 может быть лучше, поскольку он менее подвержен ошибкам, так как кто-то может легко добавить другой конструктор и забыть о его цепочке.
  • Если выЕсли у вас один конструктор и нет логического потока, который зависит от базового порядка конструктора, то case2 кажется лучше, так как это сделает код чище.[без обид, личные предпочтения]
0 голосов
/ 30 января 2019

Разница здесь действительно тонкая и может быть оценена только в легко в IL:

class MyBuilder1
{
    private MySynchronizer m_synchronizer = new MySynchronizer();

    public MyBuilder1()
    {

    }
}

дает нам конструктор:

.method public hidebysig specialname rtspecialname 
    instance void .ctor () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 18 (0x12)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: newobj instance void MySynchronizer::.ctor()
    IL_0006: stfld class MySynchronizer MyBuilder1::m_synchronizer
    IL_000b: ldarg.0
    IL_000c: call instance void [mscorlib]System.Object::.ctor()
    IL_0011: ret
} // end of method MyBuilder1::.ctor

где-как это:

class MyBuilder2
{
    private MySynchronizer m_synchronizer;

    public MyBuilder2()
    {
      m_synchronizer = new MySynchronizer();

    }
}

дает нам:

// Methods
.method public hidebysig specialname rtspecialname 
    instance void .ctor () cil managed 
{
    // Method begins at RVA 0x2063
    // Code size 18 (0x12)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: call instance void [mscorlib]System.Object::.ctor()
    IL_0006: ldarg.0
    IL_0007: newobj instance void MySynchronizer::.ctor()
    IL_000c: stfld class MySynchronizer MyBuilder2::m_synchronizer
    IL_0011: ret
} // end of method MyBuilder2::.ctor

Разница заключается просто в следующем:

  • инициализаторы поля (MyBuilder1) происходит до вызов конструктора базового типа (здесь object является базой; call instance void [mscorlib]System.Object::.ctor() является вызовом конструктора базы)
  • конструкторы происходят после вызов конструктора базового типа

В большинстве случаев это не имеет значения .Если ваш базовый конструктор не вызовет виртуальный метод, который переопределяет производный тип: то будет ли поле иметь значение в переопределенном методе, будет отличаться между ними.

...