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

Возможный дубликат:
   Лучшая практика: инициализировать поля классов в конструкторе или декларации?

это простое и даже немного глупое сомнение в том, что меня и моих друзей подняли, говоря о нашем текущем проекте.

Я хочу знать, есть разница между вызовом метода для установки переменной внутри и снаружи конструктора класса с использованием C#, как в примере ниже:

Дело 1:

public class Test
{
    string myVar = GetValue();

    public Test()
    {
    }
}

Случай 2:

public class Test
{
    string myVar;

    public Test()
    {
        myVar = GetValue(); 
    }
}

Существуют ли различия в производительности или какие-либо «нарушения шаблонов» при использовании любого из этих подходов? Я был бы очень признателен, если бы кто-нибудь мог сказать мне, какой из этих подходов лучше и что действительно происходит, когда я использую их на уровне компилятора.

Заранее спасибо!

0
nl ja de
Нет никакой реальной разницы. Для получения дополнительной информации обратитесь к этому разделу stackoverflow.com/questions/24551/… (дублировать?)
добавлено автор lahsrah, источник
@sylon, очень хорошая ссылка. помечен как дубликат
добавлено автор Habib, источник
если GetValue является статическим, вы можете.
добавлено автор Rafal, источник
Да, забыл упомянуть, что это статический метод.
добавлено автор EngFabioDario, источник
спасибо силону и Антонио БД, сообщения, на которые вы ссылались, имеют именно то, что я хотел знать!
добавлено автор EngFabioDario, источник

4 ответы

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

Одна вещь, о которой нужно знать, - порядок выполнения поскольку он может меняться в зависимости от вашей иерархии классов.

1
добавлено
@ lazyberezovsky +1 да, хорошо, это может быть не сразу очевидным.
добавлено автор James, источник
Просто отметим - поля инициализируются также перед вызовом конструктора базового класса. Когда вы инициализируете переменную в конструкторе производного класса, она будет инициализирована после вызова конструктора базового класса.
добавлено автор Sergey Berezovskiy, источник
хорошая информация, спасибо!
добавлено автор EngFabioDario, источник

Если ваш метод GetValue является статическим методом в вашем классе, вы можете использовать его в Field Initialization. Если это метод экземпляра, вы получите сообщение об ошибке.

Ваш первый код использует Field Initialization, тогда как во втором коде вы инициализируете поле в конструкторе.

Поля C#

Поля инициализируются непосредственно перед конструктором для   экземпляр объекта, поэтому, если конструктор присваивает значение   поле, оно перезапишет любое значение, указанное во время объявления поля.

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

1
добавлено

Один случай, когда инициализация поля может быть осуществимой, а читаемость читаемости - в следующем случае

class Test
{
    string myVar;
    string anotherVar;

    public Test()
    {
        myVar = "one default";
        anotherVar = "another default";
    }
    public Test(string s) //: this()
    {
        myVar = s;
        anotherVar = "another default";
    }
}

Вероятно, вы не хотите вызывать конструктор по умолчанию, потому что он может быть ошибочным в некоторых случаях для инициализации некоторой переменной два раза (в моем случае это окончательно нормально); Поэтому в приведенном выше примере я переместил anotherVar в инициализацию поля.

Note: speaking about performance, which I don't on such nano-optimization levels - when you use field initialize your field receive it first value as desired. When you initialize it from constructor, it already have its default value, so technically speaking you assign a field twice. But this penalty is so small, that I can't imagine scenarios, in which it is plausible.

0
добавлено
Вы правы, у меня такое же впечатление.
добавлено автор EngFabioDario, источник

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

1. Статическое поле и статический метод

public class Test
{
    static string myVar = GetValue();

    public Test()
    {
    }

    static string GetValue()
    {
        return String.Empty;
    }
}

В этом случае не имеет значения, где вы устанавливаете статическое поле: в конструкторе static (не представленном в коде) или в качестве инициализации статического поля. CLR будет инициализироваться как при загрузке типа в AppDomain. (Существует последовательность, такая как CLR вызывает статический конструктор вначале, а затем устанавливает все статические поля или наоборот - эта последовательность вышла из вашего контроля, хотя).

2. Настройка свойства в конструкторе

public class Test1
{
    string MyVar{get;set;}

    public Test1()
    {
        MyVar = GetValue();
    }

    string GetValue()
    {
        return String.Empty;
    }
}

Это зависит от типа и использования. В этом конкретном случае я, вероятно, избегал бы этого делать, поскольку конструктор должен был быть легким. Если вы выполняете какую-либо тяжелую обработку, лучше переместить это в метод Initialize с правильной обработкой ошибок и блоками try-catch . Если вы не выполняете тяжелую работу, чтобы настроить свойство, просто поместите значение по умолчанию в конструктор, например MyVar = "EMPTY" .

3. Установить свойство в другом классе.

public class Test
{
    public string MyVar{get;set;}

    public Test(){ }

    public string GetValue()
    {
        return String.Empty;
    }
}

//somewere else 
Test t = new Test();
t.MyVar = t.GetValue();

Это выглядит немного странно, поскольку класс предоставляет состояние (свойство) и означает получение текущего состояния (метод GetValue). Два члена (свойство и метод) в этом случае, вероятно, должны быть объединены в один getter .

0
добавлено
Спасибо за подробное объяснение! Это дополняет два ответа выше.
добавлено автор EngFabioDario, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Software Design and OOP
Software Design and OOP
1 481 участник(ов)

OOP, software design, architecture, GRASP, GoF, SOLID, separation of concerns, безысходность. Пожалуйста, придерживайтесь указанных тем. https://oopru.github.io More cool stuff: @fp_ru @tdd_ru @coding_interview_ru @coding_ru

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot