Подразумевает ли статика отсутствие состояния

Недавно я дал рекомендацию одному из моих коллег, заявив, что в нашем текущем проекте (C#) «сервисы должны быть без состояния и, следовательно, статичными».

Мой коллега согласился и указал, что в нашем проекте сервисы действительно (и должны быть) без гражданства. Однако мой коллега не согласился с тем, что статика подразумевает отсутствие состояния и что безгражданство должно означать статику.

Мои вопросы: «Подразумевает ли метод, помеченный как статический, что он не требует состояния и что в большинстве случаев методы без состояния должны быть статичными».


person Community    schedule 27.10.2009    source источник


Ответы (13)


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

person Rex M    schedule 27.10.2009
comment
@Rex, я не думаю, что технически правильно называть определение класса экземпляром класса. В куче нет структуры данных для самого класса. Статические переменные хранятся в самом определении класса, которое НЕ является экземпляром класса. Когда вы кодируете синглтон, создается один и только один экземпляр... Определение класса (где хранятся статические поля, не является еще одним вторым экземпляром... и когда ни один экземпляр не был создан для класса, то, что класс имеет одну или несколько статических переменных, не означает, что у него есть один экземпляр... - person Charles Bretana; 27.10.2009
comment
@Charles Я думаю, что это скорее философская дискуссия, чем то, где хранятся байты. - person Rex M; 27.10.2009
comment
@ Рекс, я думаю, я мог бы согласиться с этой характеристикой, но если вы хотите сказать, что это не важно, я бы вежливо попросил вас пересмотреть свое мнение. Различие, безусловно, имеет больше последствий, чем просто то, где хранятся байты. Экземпляры могут исчезнуть (при сборке мусора), и их значения на уровне экземпляра исчезнут вместе с ними. Статические поля хранятся вместе с определением класса, которое НЕ является экземпляром и, поскольку оно никогда не исчезает, имеет постоянное время жизни (до выгрузки AppDomain) - person Charles Bretana; 27.10.2009
comment
Вы оба правы (я узнал это в Калифорнии): это все еще экземпляр, и в этом экземпляре все еще есть состояние. Но экземпляр относится не к классу Foo, а к классу класса (в зависимости от языка). Или что-то вроде того... - person Dan Rosenstark; 27.10.2009
comment
@Charles Я не думаю, что несправедливо характеризовать это как экземпляр. Тип и все статические члены типа инициализируются и сохраняются в куче при первом доступе к типу, и даже если они не получают сборщик мусора, это не обязательно означает что-либо. - person Rex M; 27.10.2009
comment
@ Чарльз, если я не понял Рекса неправильно, он прав, но я думаю, что ты читаешь его по-другому. Я прочитал его. Существует еще экземпляр, относящийся к статическим переменным внутри класса. Рассмотрим class A { static String B = "boo"; } -- здесь B является экземпляром String, даже если экземпляр A никогда не создавался. - person NVRAM; 27.10.2009
comment
@NVRAM Я действительно имею в виду, что есть статический экземпляр. Существует единственный экземпляр Type, который существует на протяжении всего срока службы AppDomain, и все статические элементы инициализируются и хранятся вместе с ним в куче. - person Rex M; 27.10.2009
comment
Если бы на самом деле не было экземпляра Типа, то не могло бы быть и статического конструктора (cctor), который вызывается, когда (или до) вызывается первый статический метод или свойство, и может использоваться для инициализации статические элементы данных -- MSDN. Следовательно: есть cctor, который выделяет статический экземпляр, который является экземпляром типа. - person Abel; 27.10.2009
comment
Ко всем: статический конструктор правильнее называть инициализатором. Он не создает экземпляр, он инициализирует тип. И экземпляр «типа» не является экземпляром «класса». Я цитирую Don Boxes Essential .Net. Большинство членов класса могут быть определены как для каждого экземпляра или для каждого типа (на основе экземпляра или статического). для члена экземпляра требуется экземпляр типа для доступа к нему. Член на тип не имеет этого требования. В C# значение по умолчанию для каждого экземпляра. ... измените это на для каждого типа, используя статическое ключевое слово. - person Charles Bretana; 27.10.2009
comment
При создании фактического экземпляра создается переменная, которая содержит ссылку (адресный указатель) на объект в куче, который содержит указатель (называемый htype) на другую структуру памяти с именем CORINFO_CLASS_STRUCT. Эта структура является представлением ТИПА и содержит все определения для типа и (вероятно) там, где хранятся все статические поля. Каждый тип, используемый в вашем коде, получает CORINFO_CLASS_STRUCT один раз и только один раз до первого использования типа. Это не «экземпляр» Типа, это структура данных, представляющая Тип. - person Charles Bretana; 27.10.2009
comment
Итак, подведем итог: этот CORINFO_CLASS_STRUCT, созданный при первом использовании Type, является представлением Type , а не экземпляром типа. Это не просто семантика, потому что CORINFO_CLASS_STRUCT полностью отличается по структуре и функциям от того, что создается в куче как экземпляр типа. На самом деле, если вы напишете Type myTyp = typeof(MyClass);, новый объект в куче будет иметь тип «Type», а не «MyClass», и будут созданы два CORINFO_CLASS_STRUCT (если это первая ссылка на каждый), по одному для Введите «Тип» и один для типа «MyClass». - person Charles Bretana; 27.10.2009
comment
@Rex, если все это обсуждение связано только с тем, что вы используете слово «экземпляр» для обозначения CORINFO_CLASS_STRUCT, созданного для каждого типа при первом использовании типа, пожалуйста, прочитайте немного больше об этой структуре данных и о том, что она делает. Он сильно отличается от всех других сконструированных «экземпляров» этого типа. имхо, использование слова «экземпляр» для обозначения этой структуры данных сообщает среднему пользователю .Net много ложного, и поэтому я бы не советовал этого делать. - person Charles Bretana; 27.10.2009
comment
Еще один интересный момент заключается в том, что вы получаете CORINFO_CLASS_STRUCT для каждого типа, на который вы ссылаетесь... Итак, если в вашем коде есть класс, определенный как Dog, который наследуется от Mammal, который наследуется от Animal, который наследуется от Object, в первый раз вы используете Dog в своем коде, вы получите ЧЕТЫРЕ (4) структуры данных CORINF_CLASS_STRUCT, по одной для каждого типа, на который вы ссылались, даже если ссылка была на статическое поле в Dog. Вы действительно хотите сказать, что теперь у вас есть 4 экземпляра Dog? - person Charles Bretana; 27.10.2009

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

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

в большинстве случаев методы без сохранения состояния должны быть статичными

2) Да. Методы, не требующие состояния, а значит, не требующие экземпляра, обычно следует делать статическими.

person André Pena    schedule 27.10.2009
comment
Марк вообще. Я согласен, но слишком часто, когда люди узнают, что тот или иной метод не требует состояния, они меняют его на static. Но если действие связано с объектом с состоянием и если считается, что его использование выполняется из экземпляра (т. е. ощущение метода), метод не следует делать статическим. - person Abel; 27.10.2009

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

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

person Michael Petrotta    schedule 27.10.2009

Мне кажется довольно пугающим сказать, что без сохранения состояния — это то же самое, что и статический, поскольку это два разных мира. Без сохранения состояния означает, что состояние не сохраняется, т. е. прекрасным примером является HTTP-соединение (после отправки данных соединение закрывается и память не сохраняется), где мы на самом деле пытаемся сделать все возможное, чтобы сохранить состояние независимо от (логин состояние на одного).

С другой стороны, статический — это термин, используемый для описания способа вызова метода. В C# это означает, что метод может быть вызван без экземпляра класса, но экземпляр класса — это не то же самое, что состояние. Есть еще статический экземпляр, который прекрасно поддерживает состояние: любая статическая переменная-член, поле или свойство могут поддерживать состояние. Статический метод или класс также вполне способен поддерживать состояние, используя файлы с отображением памяти, базу данных или что-то еще. Static - это соглашение о вызовах, не более того, и оно не связано с отсутствием гражданства или нет.

person Abel    schedule 27.10.2009

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

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

Службы без сохранения состояния могут (и были) реализованы на языках, которые поддерживают только статические переменные (например, COBOL, RPG), и на языках, которые даже не допускают статических переменных (Erlang и т. д.).

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

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

person James Anderson    schedule 27.10.2009

static – это ключевое слово языка, а state – концепция дизайна. Между этими двумя вещами существует очевидная связь, но это связь конкретного с метафизическим, а не связь причины и следствия. Статические методы могут ссылаться на некоторые виды информации о состоянии.

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

person Paul Keister    schedule 27.10.2009

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

person Oren Mazor    schedule 27.10.2009

Краткий ответ на ваш вопрос: «нет», static не означает «нет состояния».

Что касается других ваших комментариев, static можно использовать, чтобы помочь вам реализовать службу без сохранения состояния, но одного static недостаточно. Еще один инструмент/метод, помогающий сделать что-то без состояния, — это использование неизменяемых структур данных. Это (в настоящее время) не является одной из сильных сторон C#, особенно по сравнению с F#.

person Ðаn    schedule 27.10.2009

Помимо перефразирования всех возможных определений «статических», ответ будет «да». Статические методы могут легко изменить состояние самого класса (представленного через статические переменные) и >даже изменять состояние экземпляров класса (в частности, когда им передается экземпляр или набор экземпляров). Однако в большинстве случаев вы будете использовать статические методы в тех случаях, когда состояние не изменяется. Наиболее важным примером является поиск или создание экземпляра (фабричные методы).

Тем не менее, правильный ответ — "нет". В реальной жизни (например, веб-службы через HTTP или взаимодействие с любым видом Orb) службы никогда не раскрывают свои методы службы, используя настоящие статические методы. Обычно вы вызываете статические методы, чтобы получить экземпляр службы (или экземпляр фабрики служб, из которой вы получаете экземпляр!), а затем работаете с этим. Это связано с тем, что прокси-сервер службы должен отслеживать свое внутреннее состояние. Таким образом, хотя ваши методы кажутся вам не имеющими состояния, на самом деле это не так.

Надеюсь, это не было слишком запутанным :)

person Dan Rosenstark    schedule 27.10.2009

Статический класс не является апатридом. Он по-прежнему может иметь переменные, которые, хотя и являются статическими, имеют состояние.

Статический класс без каких-либо переменных уровня класса не имеет состояния. Он не содержит данных.

person Kirk Broadhurst    schedule 27.10.2009

Каждый класс имеет структуру определения класса, в которой представлены и хранятся статические поля. Каждый «экземпляр» класса имеет доступ к статическим полям, хранящимся в определении класса (структура данных, называемая CORINFO_CLASS_STRUCT). Даже если НИКАКИХ экземпляров не было создано, код в любом месте вашей сборки может получить доступ к этим статическим полям уровня класса, используя синтаксис classname.StaticFieldName, вообще без какого-либо экземпляра.

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

Еще более важно то, что после загрузки определения класса CORINFO_CLASS_STRUCT, в отличие от истинного экземпляра класса, оно никогда не выгружается до тех пор, пока не будет выгружена сборка (или AppDomain). , так что, возможно, он более чувствителен, чем любое поле экземпляра, определенное в классе, потому что поле экземпляра исчезает, когда экземпляр подвергается сборке мусора.

Для получения дополнительной информации перейдите по CORINFO_CLASS_STRUCT ссылке на замечательную книгу Дона Боксеса, Essential .Net

person Charles Bretana    schedule 27.10.2009

Это в целом правильно. Однако у вас могут быть статические переменные, которые позволяют вашим статическим методам иметь состояние. Например, возьмем этот класс FooBarFactory:

class FooBarFactory
{
    private static _id = 0;
    public FooBar MakeAFooBar()
    {
        FooBar foo = new FooBar();
        foo.ID = _id;
        _id++;
    }
}
class FooBar
{
    public int ID {get;set;}
}

В этом случае ваш статический метод имеет минимальное состояние, но это (вероятно) необходимо.

person RCIX    schedule 27.10.2009
comment
Вы, возможно, хотели сказать, что это (вероятно) не нужно? - person Abel; 27.10.2009

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

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

person Cylon Cat    schedule 27.10.2009