Должен ли я всегда делать свои методы статическими, где это возможно?

Я часто задумывался над этим ... наверное, это идиотский вопрос, но начнем.

Скажем, у меня есть этот класс:

public class SomeClass
{
    public int AProperty { get; set; }

    public void SomeMethod()
    {
        DoStuff(AProperty);
    }
}

Есть ли в этом какие-то преимущества:

public class SomeClass
{
    public int AProperty { get; set; }

    public static void SomeMethod(int arg)
    {
        DoStuff(arg);
    }
}

Единственное очевидное преимущество - теперь у меня есть прямой доступ к SomeMethod.

Итак, это хорошая практика - делать такие методы статичными, если позволяет небольшой рефакторинг, или это пустая трата моего времени?

РЕДАКТИРОВАТЬ: Я забыл упомянуть (и комментарий ShellShock напомнил мне), что причина, по которой я спрашиваю, заключается в том, что я использую ReSharper, и он всегда делает предложения, что «Метод X можно сделать статическим» и так далее ...


person Nobody    schedule 13.09.2010    source источник
comment
возможный дубликат статического и нестатического метода   -  person Fredrik Mörk    schedule 13.09.2010
comment
Если для метода не требуются данные, относящиеся к конкретному экземпляру, вы можете сделать его статическим.   -  person halfdan    schedule 13.09.2010
comment
Я знаю Хальфдана, но спрашиваю - А должен ли я?   -  person Nobody    schedule 13.09.2010
comment
Это интересный вопрос. Не могу ответить, потому что у меня недостаточно XP для этого. Однако вот интересная ссылка, в которой спорят, где использовать или нет ключевое слово static: codebetter.com/blogs/patricksmacchia/archive/2009/11/16/   -  person Florian    schedule 13.09.2010


Ответы (5)


Static не зло. Static - зло при неправильном использовании, как и многие части нашего набора инструментов для программирования.

Static может быть очень выгодным. Как указывает принятый здесь ответ, static может иметь потенциальное улучшение скорости.

Как правило, если метод не использует какие-либо поля класса, то самое время оценить его функцию, однако в конечном итоге полезные методы, которые можно вызывать без создания экземпляра объекта, часто могут быть полезны. Например, классы DirectoryInformation и FileInformation содержат полезные статические методы.

Изменить

Считайте своим долгом указать, что издевательство становится намного сложнее, но его все же можно проверить.

Это просто означает, что вам нужно больше думать о том, где static методы, чтобы вы всегда могли их протестировать, не полагаясь на макет / заглушку. (то есть: не помещайте их в свой DTO, который требует постоянного подключения к базе данных).

person Michael Shimmins    schedule 13.09.2010

Я попытаюсь ответить на ваш конкретный вопрос, используя предоставленный вами образец кода.

Если SomeMethod полезен только в классе, в котором он объявлен, я бы избегал статического преобразования и оставил его как метод экземпляра.

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

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

В качестве (очень простого) примера, где статика является злом, но может быть преобразована в незлую версию, представьте функцию, которая вычисляет чей-то возраст:

static TimeSpan CalcAge(DateTime dob) { return DateTime.Now - dob; }

Это можно проверить? Ответ - нет. Он основан на чрезвычайно нестабильном статическом состоянии DateTime.Now. Вам не гарантируется каждый раз одинаковый результат для одного и того же входа. Чтобы сделать его более удобным для тестирования:

static TimeSpan CalcAge(DateTime dob, DateTime now) { return now - dob; }

Теперь все значения, на которые опирается функция, переданы, и это полностью проверено. Один и тот же ввод даст вам тот же результат.

person Alex Humphrey    schedule 13.09.2010
comment
Вы говорите, что если метод полезен только внутри класса, не делайте его статичным. Разве это не повышение производительности за счет статического метода? Или еще какой смысл иметь метод private static (который возможен и фактически предложен ReSharper)? - person awe; 12.03.2012
comment
@awe - вы правы, что вызов статических методов должен быть быстрее. Однако для этого конкретного примера я считаю, что вызов someClassInstance.SomeMethod() лучше, чем SomeClass.SomeMethod(someClassInstance.AProperty). Я не думаю, что предложенный в вопросе рефакторинг - лучший вариант - во многих других случаях так и есть. Предлагает ли ReSharper этот рефакторинг для приведенного выше примера? Меня бы удивило, если бы это произошло, когда метод обращается к свойству экземпляра. Вы можете пойти на все и написать static SomeMethod(SomeClass this) для всех своих невиртуальных методов экземпляра, если хотите. - person Alex Humphrey; 13.03.2012
comment
Я согласен с вами в этом случае, но вы сформулировали это так, что мне было непонятно. Я имею в виду в примере, где метод полезен только в контексте класса, но технически не использует ни один из членов класса. Этот метод на самом деле представляет собой своего рода служебную функцию, но никакой другой код, кроме кода внутри класса, не нуждается в этой функции. Resharper предлагает провести рефакторинг, если ваш метод не использует никаких нестатических членов или методов в вашем классе. Я заметил это в созданном мной частном методе, который ReSharper предложил сделать статическим. - person awe; 13.03.2012
comment
@awe - В вашем примере я согласен сделать метод статическим и оставить его в классе. На самом деле для меня это довольно распространенный рефакторинг. - person Alex Humphrey; 13.03.2012
comment
Примечание по производительности. Статическая функция и невиртуальный метод имеют одинаковые характеристики производительности для каждого вызова. Что делает статическую функцию быстрее, так это то, что вам не нужно создавать экземпляр объекта перед его вызовом. Это означает, что у вас на один объект меньше для GC. - person Jonathan Allen; 14.08.2016

Нет. Статика - это зло. Он тесно связывает вызывающего с используемым классом и затрудняет тестирование.

person Sjoerd    schedule 13.09.2010
comment
Инструмент анализа кода Microsoft всегда предлагает сделать методы статическими, если нет зависимостей экземпляров. Это плохой совет? - person Polyfun; 13.09.2010
comment
@ShellShock Может быть. Если у вас много таких методов, вы, вероятно, нарушаете принципы ООП. Метод объекта должен (почти) всегда работать с данными, связанными с объектом. - person Karel Petranek; 13.09.2010
comment
@dark_charlie: Итак, вы говорите, что если у вас есть метод как статический, вам следует реструктурировать его, чтобы вместо этого поместить его в статический служебный класс? Что, если метод логически привязан к классу, но технически не использует никаких членов? - person awe; 12.03.2012
comment
Правильный ответ, конечно, зависит от обстоятельств. Есть сценарии, в которых статический метод принадлежит классу. Но это довольно редко, и общее правило - избегать статических методов. - person Karel Petranek; 12.03.2012
comment
Эээ, Math.Max нетрудно проверить. - person Jonathan Allen; 14.08.2016

Статические методы имеют смысл, если вы должны иметь возможность вызывать их без предварительного создания объекта класса. В Java, например, Math-Class содержит только статические методы, потому что было бы бессмысленно создавать экземпляр Math-Class только для выполнения математических операций с другими объектами.

В большинстве случаев лучше избегать статических методов. Вам следует познакомиться с объектно-ориентированным программированием - есть много хороших ресурсов, объясняющих все концепции, такие как статические методы и т. Д.

person cyphorious    schedule 13.09.2010

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

В качестве примера предположим, что у вас есть строковый класс и две строки A и B. Для сравнения A и B вы можете использовать метод A.CompareTo (B) или метод String.Compare (A, B).

Пожалуйста, поправьте меня, если я ошибаюсь.

person Rahul    schedule 13.09.2010
comment
Я думаю, что XDocument.Parse был бы лучшим примером. Нет особого смысла в создании XDocument только для того, чтобы использовать его метод синтаксического анализа для создания XDocument, который вам действительно нужен. - person Jonathan Allen; 14.08.2016