Почему C # не позволяет объявлять переменные статическими в методах? - PullRequest
0 голосов
/ 09 сентября 2011

Я читаю некоторые примеры AppHub от Microsoft, и это начало одной из функций:

if (string.IsNullOrEmpty(textureFilename))
{
    string message = "textureFilename wasn't set properly, so the " +
        "particle system doesn't know what texture to load. Make " +
        "sure your particle system's InitializeConstants function " +
        "properly sets textureFilename.";
    throw new InvalidOperationException(message);
}

ReSharper говорит, чтобы сделать это значение постоянным, а не повторять его каждый раз. Тем не менее, это строковое значение используется только в этой функции, поэтому нет необходимости делать его переменной-членом. В идеале область действия переменной должна быть ограничена этой функцией. Правильно?

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

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

Visual Basic .NET позволяет программисту объявлять переменные в функции как статические. Например, в этом коде TestFunction будет вызываться только при первом нажатии кнопки:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Static example As Integer = TestFunction()

    MessageBox.Show(example)
End Sub

Private Function TestFunction() As Integer
    Console.WriteLine("Method Accessed")

    Return 5
End Function

Насколько я знаю, C # не позволяет этого. Есть ли какая-то конкретная причина, почему? Кажется, что это было бы идеально в этой ситуации. Он ограничивает область видимости переменных функцией и инициализирует ее только в первый раз. Даже если создание объекта является дорогостоящим, оно будет выполнено только один раз. Так почему же это недоступно? Или это?

Спасибо за чтение!

Ответы [ 3 ]

4 голосов
/ 09 сентября 2011

ReSharper говорит, чтобы сделать это значение постоянным, а не повторным выделением это каждый раз. Однако это строковое значение используется только в этом функция, поэтому сделать ее переменной-членом не нужно. В идеале область действия переменной должна быть ограничена этой функцией. Правильно?

Да, но resharper сделает локальную переменную const, а не создаст поле члена

if (string.IsNullOrEmpty(textureFilename))
{
    const string message = "textureFilename wasn't set properly, so the " +
        "particle system doesn't know what texture to load. Make " +
        "sure your particle system's InitializeConstants function " +
        "properly sets textureFilename.";
    throw new InvalidOperationException(message);
}
1 голос
/ 09 сентября 2011

В этом часто задаваемом вопросе по C # есть сообщение об этом точном вопросе .

Фактически, есть две причины.Во-первых, вы можете сделать то же самое через const или через статическую переменную уровня члена почти во всех ситуациях.Во-вторых, локальные статические переменные в других языках (таких как C и C ++) часто вызывают проблемы в многопоточных сценариях.

Кроме того, я рад, что это было опущено.Состояние, как данные, как в C #, существует только в привязке к типу или экземпляру.Это могло бы сделать третий способ хранения состояния и добавить путаницу.

Относительно того, почему VB.Net включил это - это было включено для обратной совместимости с VB.При этом компилятор фактически превращает это в статический член типа, так что его уровень поддержки действительно такой же, как в C #.

1 голос
/ 09 сентября 2011

Есть ли причина, по которой вы не хотите делать его локальным const, как предлагает ReSharper?

if (string.IsNullOrEmpty(textureFilename))
{
    const string message = "...";
    throw new InvalidOperationException(message);
}
...