У меня есть несколько классов, которые действительно не нуждаются в каком-либо состоянии. С организационной точки зрения я бы хотел поместить их в иерархию.
Но, похоже, я не могу объявить наследование для статических классов.
Что-то такое:
public static class Base
{
}
public static class Inherited : Base
{
}
не будет работать.
Почему разработчики языка закрыли эту возможность?
c#
inheritance
static
пользователь
источник
источник
Ответы:
Цитата отсюда :
Другие мнения от channel9
И, как ценная идея, у littleguru есть частичный «обходной путь» для этой проблемы: шаблон Singleton .
источник
object
, и все, как ожидается, будут это знать. Таким образом, статические классы всегда наследуютсяobject
независимо от того, указали вы это явно или нет.Основная причина того, что вы не можете наследовать статический класс, состоит в том, что они абстрактны и запечатаны (это также предотвращает создание любого их экземпляра).
Итак, это:
компилируется в этот IL:
источник
Подумайте об этом так: вы получаете доступ к статическим членам через имя типа, например так:
Если бы вы унаследовали от этого класса, вы бы получили к нему доступ через имя нового типа:
Таким образом, новый элемент не имеет отношения к оригиналу при использовании в коде. Не было бы никакого способа использовать в своих интересах любые отношения наследования для таких вещей, как полиморфизм.
Возможно, вы думаете, что просто хотите расширить некоторые предметы в исходном классе. В этом случае ничто не мешает вам использовать элемент оригинала в совершенно новом виде.
Возможно, вы хотите добавить методы к существующему статическому типу. Вы можете сделать это уже с помощью методов расширения.
Возможно, вы хотите иметь возможность передавать статические
Type
функции в функцию во время выполнения и вызывать метод этого типа, не зная точно, что делает метод. В этом случае вы можете использовать интерфейс.Итак, в конце концов, вы ничего не получите от наследования статических классов.
источник
SomeClass<T> where T:Foo
мог получить доступ к членамFoo
, и если бы этоT
был класс, который переопределял некоторые виртуальные статические членыFoo
, универсальный класс использовал бы эти переопределения. Вероятно, было бы даже возможно определить соглашение, посредством которого языки могли бы делать это способом, совместимым с текущим CLR (например, класс с такими членами должен определять защищенный нестатический класс, который содержит такие элементы экземпляра вместе со статическим полем держа экземпляр этого типа).То, чего вы хотите достичь с помощью иерархии классов, может быть достигнуто просто с помощью пространства имен. Поэтому языки, которые поддерживают пространства имен (например, C #), не будут использовать реализацию иерархии классов статических классов. Поскольку вы не можете создать экземпляр какого-либо из классов, все, что вам нужно, - это иерархическая организация определений классов, которую вы можете получить, используя пространства имен
источник
Вместо этого вы можете использовать композицию ... это позволит вам получить доступ к объектам класса из статического типа. Но все еще не могу реализовать интерфейсы или абстрактные классы
источник
Хотя вы можете получить доступ к «унаследованным» статическим членам через имя унаследованных классов, статические члены на самом деле не наследуются. Это частично, почему они не могут быть виртуальными или абстрактными и не могут быть переопределены. В вашем примере, если вы объявили Base.Method (), компилятор все равно отобразит вызов Inherited.Method () обратно в Base.Method (). Вы также можете явно вызвать Base.Method (). Вы можете написать небольшой тест и увидеть результат с помощью Reflector.
Итак ... если вы не можете наследовать статические члены, и если статические классы могут содержать только статические члены, что хорошего в наследовании статического класса?
источник
Хммм ... было бы очень по-другому, если бы у вас были нестатические классы, заполненные статическими методами ..?
источник
Обходной путь, который вы можете сделать, - это не использовать статические классы, а скрыть конструктор, чтобы статические члены классов были единственными доступными за пределами класса. В результате получается наследуемый «статический» класс:
К сожалению, из-за языкового ограничения "by-design" мы не можем:
источник
Вы можете сделать что-то похожее на статическое наследование.
Вот хитрость:
Тогда вы можете сделать это:
Сам
Inherited
класс не является статичным, но мы не позволяем его создать. Он фактически унаследовал статический конструктор, который строитBase
, и все свойства и методыBase
доступны как статические. Теперь остается только сделать статические оболочки для каждого метода и свойства, которые вам необходимо предоставить для вашего статического контекста.Есть недостатки, такие как необходимость ручного создания статических методов-оберток и
new
ключевых слов. Но этот подход помогает поддерживать то, что действительно похоже на статическое наследование.PS Мы использовали это для создания скомпилированных запросов, и это на самом деле можно заменить на ConcurrentDictionary, но статическое поле только для чтения с его безопасностью потока было достаточно хорошим.
источник
Мой ответ: неудачный выбор дизайна. ;-)
Это интересная дискуссия, посвященная влиянию синтаксиса. Суть аргумента, на мой взгляд, заключается в том, что проектное решение привело к запечатанным статическим классам. Акцент на прозрачности имен статических классов, появляющихся на верхнем уровне, вместо того, чтобы прятаться («сбивать с толку») за дочерними именами? Можно представить себе языковую реализацию, которая может напрямую обращаться к базе или к ребенку, что может сбить с толку.
Псевдо-пример, предполагающий статическое наследование, был определен некоторым образом.
приведет к:
который может (будет?) влиять на то же хранилище, что и
Очень запутанно!
Но ждать! Как компилятор будет иметь дело с MyStaticBase и MyStaticChild, имеющими одинаковую сигнатуру, определенную в обоих? Если ребенок переопределяет, чем мой приведенный выше пример, НЕ изменится то же хранилище, может быть? Это приводит к еще большему замешательству.
Я считаю, что существует сильное информационное пространство для ограниченного статического наследования. Подробнее о пределах в ближайшее время. Этот псевдокод показывает значение:
Тогда вы получите:
Использование выглядит так:
Создателю статического потомка не нужно думать о процессе сериализации, если он понимает любые ограничения, которые могут быть наложены на механизм сериализации платформы или среды.
Статика (синглтоны и другие формы глобалов) часто возникает вокруг хранилища конфигурации. Статическое наследование позволило бы четко представить такое распределение ответственности в синтаксисе, чтобы оно соответствовало иерархии конфигураций. Хотя, как я показал, существует большой потенциал для неоднозначности, если реализовать базовые концепции статического наследования.
Я считаю, что правильным выбором дизайна было бы позволить статическое наследование с конкретными ограничениями:
Вы все еще можете изменить тот же магазин через общую ссылку
MyStaticBase<ChildPayload>.SomeBaseField
. Но вы были бы обескуражены, так как общий тип должен быть указан. Пока ссылка на ребенка будет чище:MyStaticChild.SomeBaseField
.Я не пишу компилятор, поэтому я не уверен, что что-то упускаю из-за трудностей реализации этих ограничений в компиляторе. Тем не менее, я твердо убежден, что информационное пространство необходимо для ограниченного статического наследования, и основной ответ заключается в том, что вы не можете этого сделать из-за плохого (или слишком простого) выбора дизайна.
источник
Статические классы и члены класса используются для создания данных и функций, к которым можно получить доступ, не создавая экземпляр класса. Статические члены класса могут использоваться для разделения данных и поведения, которое не зависит от идентичности объекта: данные и функции не изменяются независимо от того, что происходит с объектом. Статические классы могут использоваться, когда в классе нет данных или поведения, которое зависит от идентичности объекта.
Класс может быть объявлен статическим, что означает, что он содержит только статические члены. Невозможно использовать ключевое слово new для создания экземпляров статического класса. Статические классы загружаются автоматически общеязыковой средой (CLR) .NET Framework, когда загружается программа или пространство имен, содержащее класс.
Используйте статический класс, чтобы содержать методы, которые не связаны с конкретным объектом. Например, распространенным требованием является создание набора методов, которые не действуют на данные экземпляра и не связаны с конкретным объектом в вашем коде. Вы можете использовать статический класс для хранения этих методов.
Ниже приведены основные характеристики статического класса:
Они содержат только статические члены.
Они не могут быть созданы.
Они запечатаны.
Они не могут содержать конструкторы экземпляров (Руководство по программированию в C #).
Поэтому создание статического класса в основном аналогично созданию класса, который содержит только статические члены и закрытый конструктор. Закрытый конструктор предотвращает создание экземпляра класса.
Преимущество использования статического класса заключается в том, что компилятор может проверить, чтобы убедиться, что никакие члены экземпляра не были добавлены случайно. Компилятор гарантирует, что экземпляры этого класса не могут быть созданы.
Статические классы запечатаны и поэтому не могут быть унаследованы. Они не могут наследовать ни от какого класса, кроме Object. Статические классы не могут содержать конструктор экземпляра; однако они могут иметь статический конструктор. Для получения дополнительной информации см. Статические конструкторы (Руководство по программированию в C #).
источник
Когда мы создаем статический класс, который содержит только статические члены и закрытый конструктор. Единственная причина в том, что статический конструктор предотвращает создание экземпляра класса, для этого мы не можем наследовать статический класс. Единственный способ получить доступ к члену класса. статический класс с использованием самого имени класса. Попытка наследовать статический класс не очень хорошая идея.
источник