Статические методы vs методы экземпляра в C#

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

Я помню, что читал, что статические методы быстрее, чем методы экземпляра, но не получают преимуществ GC. Правильно ли это?

маловероятно, что я изменю свой дизайн, если не найду превосходную альтернативу по дизайну, а не скорости. Но все же для дополнительной информации I хотите знать различия в скорости, GC и т. д.

EDIT: спасибо. Подробнее: Допустим у нас есть класс Person:

class Person

который может иметь метод расстояния экземпляра так:

this.Distance (Person p)

это здорово, но это не дает мне возможность вычислить расстояние между 2 точками (скажем, Point3), без создания экземпляров класса Person.

что я хочу сделать это:

class Person (no Distance methods)

но методы продления Расстояние:

Distance (this Person, Person)
Distance (this Point3, Point3)

таким образом я могу сделать:

myPerson.Distance (yourPerson)

и

Extensions.Distance (pointA, pointB)

EDIT2: @Jon, да, я думаю, что это было то, что подразумевалось (не получите преимущества GC), но я почему-то думал, что статические методы создают эту нагрузку/накладные расходы.

4 ответов


что вы подразумеваете под "не получаете преимущества GC"? Методы - это не сбор мусора, а экземпляры.

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

статические методы являются болью для тестирования, хотя-например, если вы аутентифицируетесь в методе Foo() вызывая некоторый статический метод, тогда когда ты проверяешь!--0--> вы не можете заставить его просто вызвать макет аутентификатора (если только сам статический метод не позволяет вам это сделать). Если вы даете исходный экземпляр того, что вы тестируете, макет реализации некоторого интерфейса, содержащего Authenticate() метод, однако, вы можете заставить его вести себя как угодно.

EDIT: в этом случае похоже, что вам действительно нужен метод экземпляра на вашем Point введите для расчета расстояния между двумя точками ("это" и другой) - или потенциально статический заводской метод на Distance тип.


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

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


Если под более быстрым вы подразумеваете, что код внутри метода выполняется быстрее, то нет. Код в статическом методе так же быстр, как код в нестатическом методе.

Если вы говорите о накладных расходах на выполнение вызова метода, он становится немного более сложным. Это распространено для языков, поскольку Java, что вызовы экземпляра имеют больше накладных расходов. Однако в C# это не так, поскольку методы экземпляра по умолчанию не являются виртуальными.

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

Что касается сбора мусора, это в основном относится к полям, а не к методам. Статические поля могут быть доступны отовсюду в коде, поэтому сборщик мусора не может определить, будет ли ссылка использоваться снова, поэтому она никогда не собирается.


основываясь на вашем примере, я бы написал статическую функцию утилиты, чтобы найти расстояние между двумя точками:

public static class Geometry
{
    public static double GetDistanceBetween(Point a, Point b) { ... }
}

и тогда я бы дал человеку свойство под названием Position, которое вернуло точку. Чтобы я мог написать:

double distance = Geometry.GetDistanceBetween(personA.Position, personB.Position);

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

personA.Distance(personB)

или:

personB.Distance(personA)

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