Когда встроенные статические переменные инициализируются в классе? - PullRequest
1 голос
/ 10 августа 2010

Предположим, у нас есть такой класс, как:

Public Class Question 

    Private Shared _field as Integer = CrazyIntegersRepository.GetOne()

    ' Some other useful things go here

End Class

И метод GetOne вызывает исключение ... Как мы можем управлять этим?Является ли хорошей практикой переписать это в статический конструктор?
Когда будет выполняться метод GetOne, если мы оставим его там во встроенном объявлении _field?

Ответы [ 3 ]

4 голосов
/ 10 августа 2010

Примечание: я предполагаю, что VB работает так же, как C # здесь.Я был бы удивлен, если бы они отличались от этого.

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

Фактическое наблюдаемое поведение стало более медленным в .NET 4 по сравнению с .NET 3.5, , как я писал в блоге о .Обратите внимание, что речь идет только о платформе рабочего стола;Я не знаю, что делают Silverlight или Compact Framework.

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

0 голосов
/ 10 августа 2010

Если вы воспользуетесь предложением p.campbell, вам придется объявить хотя бы один экземпляр класса, чтобы инициализировать переменную _field. Из ключевого слова Shared в объявлении переменной я предполагаю, что вы хотите, чтобы она была доступна из всех экземпляров класса, независимо от того, были ли они специально инициализированы.

Чтобы реализовать эту функцию, вам нужно изменить класс следующим образом:

Public Class Question 

    Private Shared _field as Integer

    Shared Sub New()
        _field = CrazyIntergersRepository.GetOne()
    End Sub
    ' Some other useful things go here

End Class


При использовании этого метода переменная _field будет инициализирована при первом использовании класса, поскольку конструктор по умолчанию объявлен как Shared . При желании вы можете заключить метод в блок Try...Catch, чтобы перехватывать исключения, которые могут возникнуть.

0 голосов
/ 10 августа 2010

Относительно вашего вопроса об управлении возможными исключениями, подумайте об этом.Любой код, который может создать исключение, должен быть помещен в метод.В этом случае конструктор будет лучшим местом.Так что, возможно, что-то вроде:

Public Sub New()
    Try
        _field as Integer = CrazyIntegersRepository.GetOne()
    Catch ex As Exception
        'log it / deal with it as you will
    End Try
End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...