Статические методы против методов экземпляра в C # - PullRequest
6 голосов
/ 27 февраля 2009

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

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

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

РЕДАКТИРОВАТЬ: Спасибо. Дополнительная информация: Допустим, у нас есть класс Person:

class Person

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

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 ]

14 голосов
/ 27 февраля 2009

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

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

13 голосов
/ 27 февраля 2009

Что вы подразумеваете под «не получить преимущества GC»? Методы не являются сборщиком мусора - экземпляры.

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

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

РЕДАКТИРОВАТЬ: В этом случае, похоже, что вам действительно нужен метод экземпляра для вашего типа Point для расчета расстояния между двумя точками («эта» одна и другая) - или, возможно, статический метод фабрики на Distance тип.

5 голосов
/ 27 февраля 2009

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

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

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

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

2 голосов
/ 27 февраля 2009

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

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

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

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

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

personA.Distance(personB)

или

personB.Distance(personA)

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

...