Почему статические классы считаются «классами» и «ссылочными типами»? - PullRequest
23 голосов
/ 06 мая 2010

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

  • «Нормальный» класс может содержать нестатические члены, а статический класс - нет. В этом отношении класс больше похож на struct , чем на статический класс, и все же структуры имеют отдельное имя.
  • Вы можете иметь ссылку на экземпляр «нормального» класса, но не на статический класс (несмотря на то, что он считается «ссылочным типом»). В этом отношении класс больше похож на интерфейс , чем на статический класс, и все же интерфейсы имеют отдельное имя.
  • Имя статического класса никогда не может использоваться ни в каком месте, где обычно подходит имя типа: вы не можете объявить переменную этого типа, вы не можете использовать ее как базовый тип, и вы можете ' не используйте его как параметр общего типа. В этом отношении статические классы больше похожи на пространства имен .
  • «Нормальный» класс может реализовывать интерфейсы. Еще раз это делает классы более похожими на структуры , чем на статические классы.
  • «Нормальный» класс может наследоваться от другого класса.

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

Относительно аргумента подмножества функций: Статические классы имеют подмножество свойств классов, но они также имеют подмножество свойств структур. Все вещи, которые отличают класс от других типов, не относятся к статическим классам.

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

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

Ответы [ 10 ]

8 голосов
/ 06 мая 2010

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

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

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

7 голосов
/ 06 мая 2010

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

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

4 голосов
/ 06 мая 2010

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

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

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

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

4 голосов
/ 06 мая 2010

Я не знаю, квалифицируется ли это как ответ, но я бы отметил, что «статические классы» - это скорее концепция языка, а не концепция CLR. С точки зрения CLR, они просто классы, как и любые другие. Язык должен обеспечить соблюдение всех правил, которые вы описали.

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

3 голосов
/ 06 мая 2010

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

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

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

0 голосов
/ 20 июня 2013

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

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

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

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

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

0 голосов
/ 06 мая 2010

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

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

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

0 голосов
/ 06 мая 2010

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

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

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

0 голосов
/ 06 мая 2010

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

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

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

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

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

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

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

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

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

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

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

0 голосов
/ 06 мая 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...