Подтвердить что ты не робот

Почему статические классы считаются "классами" и "ссылочными типами"?

Я размышлял о системе типов С# и CIL сегодня, и Ive начал задаваться вопросом, почему статические классы считаются классами. Существует много способов, по которым они не являются классами:

  • "Обычный" класс может содержать нестатические элементы, статический класс can not. В этом отношении класс больше похож на структуру, чем на статический класс, а структуры имеют отдельное имя.
  • У вас может быть ссылка на экземпляр "нормального" класса, но не на статический класс (несмотря на то, что он считается "ссылочным типом" ). В этом отношении класс более похож на интерфейс, чем на статический класс, но все же интерфейсы имеют отдельное имя.
  • Имя статического класса никогда не может использоваться в любом месте, где обычно должно быть имя типа: вы не можете объявить переменную этого типа, вы не можете использовать ее как базовый тип, и вы не можете использовать ее как общий тип. В этом отношении статические классы несколько больше похожи на пространства имен.
  • "Обычный" класс может реализовывать интерфейсы. Еще раз, что делает классы более похожими на структуры, чем на статические классы.
  • "Обычный" класс может наследовать от другого класса.

Также странно, что статические классы считаются производными от System.Object. Хотя это позволяет им "наследовать" статические методы Equals и ReferenceEquals, цель этого наследования сомнительна, так как вы будете называть эти методы на объекте в любом случае. С# даже позволяет вам указывать это бесполезное наследование явно на статические классы, но не на интерфейсы или структуры, где на самом деле имеет место неявный вывод из объекта и System.ValueType.

Что касается аргумента subset-of-features: Статические классы имеют подмножество функций классов, но они также имеют подмножество функций struct. Все вещи, которые делают класс отличным от других типов, похоже, не применяются к статическим классам.

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

Учитывая явную странность статических классов и ограниченность сходств между ними и "нормальными" классами, не должны ли они быть сделаны отдельным типом типа вместо специального класса?

4b9b3361

Ответ 1

Да, они очень странные. У них действительно есть поведение, подобное классу, например, возможность иметь (статические) переменные-члены и ограничение доступа к членам, использующим public/private.

Я почти набрал "общедоступный/защищенный/закрытый", но явно защищенный не имеет смысла, потому что нет наследования методов статических классов. Я думаю, что основной причиной этого является то, что, поскольку нет экземпляров, вы не можете иметь полиморфизм, но на самом деле это не единственная причина наследования. Полиморфизм велик, но иногда вы просто хотите занять большую часть функциональности базового класса и добавить несколько своих вещей. Из-за этого иногда вы увидите, что статические классы переключились на использование одноэлементных паттернов, чтобы они могли использовать некоторые функции из базового набора классов. По-моему, это хакерская попытка закрыть этот пробел, и это запутывает и вводит много неестественной сложности. Другой вариант - это агрегация, где методы дочернего класса просто передают вызовы методам родительского класса, но для этого требуется много кода, чтобы все это совместить и не является идеальным решением.

В наши дни статические классы обычно просто используются в качестве замены для глобальных методов, то есть методов, которые предоставляют функциональность без привязки к экземпляру чего-либо. Пуристы OO ненавидят любую концепцию свободного/глобального всплывающего вокруг, но вы также не хотите иметь лишний экземпляр и объект, плавающие вокруг, если вам просто нужна функциональность, поэтому статический "класс" обеспечивает средний уровень компромисс, с которым обе стороны могут согласиться.

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

Ответ 2

Это класс для CLR. Это просто синтаксический сахар в компиляторе С#, в основном.

Я не думаю, что здесь было бы полезно добавить другое имя - они ведут себя в основном как классы, которые имеют только статические методы и не могут быть построены, что обычно является видом класса, ставшего статическим классом, когда мы переместились с С# 1 на С# 2.

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

Ответ 3

Ваш вопрос: "Почему мне нужно вводить слова static class X, а не foobar X". Ответ заключается в том, что программисты уже ассоциируют слово "класс" с "связкой тесно упакованной инкапсулированной функциональности, которую кто-то написал для меня". Который, по совпадению, отлично вписывается в определение статических классов.

Вместо этого они могли использовать пространства имен, да. Что происходит на С++. Но термин "статический класс" имеет преимущество здесь: он подразумевает меньшую и гораздо более тесно связанную группу функциональных возможностей. Например, вы можете иметь пространство имен с именем Qt или boost:: asio, но статический класс StringUtils или KWindowSystem (чтобы заимствовать один из KDE).

Ответ 4

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

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

Ответ 5

Конечно, их можно было разделить на отдельные вещи.

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

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

Ответ 6

Хорошая точка зрения, вероятно, из-за исторических причин, т.е. они не хотели изобретать что-то новое, поскольку уже существовали статические классы.

С++, Pascal (Delphi) и Java имеют статические классы, и на них основан С#.

Ответ 7

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

Структура, скорее всего, тип значения, как при написании:

var struct1 = new Struct1();
var struct2 = struct1;

каждое из свойств будет скопировано в новое место памяти. Кроме того, со структурой вы сможете изменить значение struct2.Property1, не изменив его в struct1.Property1.

В отличие от оппозиции, классы в моем понимании ссылочных типов, как при написании:

var class1 = new Class1();
var class2 = class1;

Здесь копируется ссылка. Это означает, что при изменении класса2.Property1 это же свойство также изменится в классе1.Property1. Это связано с тем, что оба класса указывают на один и тот же адрес памяти.

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

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

ИЗМЕНИТЬ Фактически, статический класс настолько похож на класс, что в Visual Basic отсутствует статический класс, а только класс со статическими (Shared in Visual Basic) членами. Единственный момент, который следует учитывать, - сделать этот класс NotInheritable (запечатанным на С#). Таким образом, С# обеспечивает более неявную функциональность, позволяя объявлять статический класс, а не делать его запечатанным, с пустым конструктором по умолчанию и т.д. Это какой-то ярлык или синтаксический сахар, как мы хотели бы сказать.

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

Ответ 8

Статические классы и "нормальные" классы (и структуры) являются контейнерами для исполняемого кода (поля участников, свойства, методы), и они объявляют Type. Если бы у них было отдельное слово для этого, мы бы спросили обратное ( "если они настолько похожи, почему вы не использовали класс кейлора?" ). Я бы предложил "CLR через С#", где он хорошо объяснил, как происходит разрешение типа, вызов метода и т.д. Он работает одинаково для "обоих" классов, только члены экземпляра имеют дополнительный параметр, переданный для объекта экземпляра.

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

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

Ответ 9

Хотя типы классов, типы значений и интерфейсы ведут себя во многих отношениях, как если бы они были в трех разных вещах, на самом деле все они описаны с использованием одного и того же типа объекта Type; происхождение типа определяет, что это за вещь. В частности, все типы в .NET являются типами классов, за исключением следующих:

  • Типы, отличные от System.Object, которые наследуют от null; это интерфейсы.

  • Типы, отличные от System.ValueType или System.Enum, которые наследуют от System.ValueType или System.Enum; это типы значений.

  • Несколько типов, например указатели и byrefs, которые могут быть идентифицированы объектами Type (необходимы для таких вещей, как типы параметров), но не имеют членов, как это делают другие типы.

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

Ответ 10

Как насчет статических конструкторов? Я думаю, что это еще один важный аспект, который следует учитывать при сравнении. Классы и структуры поддерживают их, но интерфейсов и пространств имен нет.

Конструкция подразумевает создание экземпляра. Хотя реализация не может фактически создать "экземпляр" статического класса, вы можете рассматривать статические классы как одноэлементный экземпляр класса, к которому может быть только одна ссылка (само имя). Если бы вы могли наследовать статические классы, вы бы сломали одноэлементное понятие. Если вы можете объявить переменные типа, вы можете ожидать, что они будут очищены сборщиком мусора, когда они больше не будут ссылаться.

Почему это классы вместо структур? Когда я думаю о структурах (типах значений), я думаю о значениях в стеке. Их существование (как правило) очень короткое, и они часто копируются. Это снова разрушает однозначное одноэлементное понятие выше.