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

Наследовать от структуры

Я пытаюсь выяснить, в чем проблема с моим кодом. У меня есть этот код:

public struct MyStructA
{
    public MyStructA(string str)
    {
        myString= str;
    }

    public string myString;
}

public struct MyStructB: MyStructA
{
    public string myReversString;
}

И я получаю эту ошибку:

Error at compile time: Type 'MyStructA' in interface list is not an interface

Я не понимаю, почему?.net not implemnet struct как класс?

4b9b3361

Ответ 1

Строка неявно запечатана

В соответствии с этой ссылкой :

Каждая структура в С#, независимо от того, определена она или определена в .NET Framework, запечатана - это означает, что вы не можете наследовать ее. Структура закрыта, потому что это тип значения, и все типы значений запечатаны.

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

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

public struct PersonName
{
    public PersonName(string first, string last)
    {
        First = first;
        Last = last;
    }

    public string First;
    public string Last;
}

// Error at compile time: Type 'PersonName' in interface list is not an interface
public struct AngryPersonName : PersonName
{
    public string AngryNickname;
}

Ответ 2

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

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

Обычное наследование требует, чтобы объекты содержали информацию о своем собственном типе, но не предусмотрено, через какие типы значений это можно сделать.

Концептуально было бы (и полезно) для .NET разрешить некоторые ограниченные формы наследования типов значений с некоторыми особыми правилами, например, когда переменная BaseStructure может содержать только BaseStructure и не может содержать DerivedStructure. Можно определить StructureUser<T> where T:BaseStructure, и такой класс или метод может принимать любую производную от BaseStructure и использовать те члены, включая поля, которые являются общими для базового типа.

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

Например, в классе Foo<T,U> where T:U всегда можно сохранить T в переменной типа U, даже если U является типом значения (т.е. Поскольку типы значений запечатаны, T и U гарантированы быть того же типа). Если бы U мог быть наследуемым типом значения, а T мог бы быть производным, такая гарантия не действовала бы.

Учитывая трудности, связанные с таким наследованием, более полезной альтернативой было бы обеспечение безопасных (даже ограниченных) средств, с помощью которых свойство могло бы предоставлять byref или const-byref (byref - это то, что передается, когда параметр использует ref классификатор).

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

Ответ 3

Struct не поддерживает наследование, если вам нужно использовать класс, см. msdn

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

Ответ 4

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

Ответ 5

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

Ответ 6

От MSDN;

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

Но помните, поскольку structs являются типом значений и наследуют System.ValueType

Ответ 7

На самом деле есть несколько веских причин:

  1. Структуры не имеют типа

    ... если они не "упакованы" в объект.

    С другой стороны, object имеет два поля "заголовка" в обычном CLR, где хранится тип (и некоторая GC- и информация о блокировке). Добавление этого изменило бы размер структур и сделало бы их размер непредсказуемым (поскольку некоторые среды выполнения могли бы добавить эту информацию по-другому, например, среда моно добавляет больше информации "заголовка" к своим объектам, чем среда выполнения платформы .net, или в меньше всего так делал в прошлом)

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

  2. Набор текста и фиксированный размер

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

    Рассмотрим две структуры: struct MyBaseStruct { public int A; } struct MyBaseStruct { public int A; } и гипотетическая struct MyDerivedStruct: MyBaseStruct { public int B; } struct MyDerivedStruct: MyBaseStruct { public int B; }

    Теперь, что произойдет, когда я вызову var array = new MyBaseStruct[10]; ?? Какой размер выделяет для этого среда выполнения?

    array[0] = new MyDerivedStruct(); присваивания array[0] = new MyDerivedStruct(); было бы проблематично, в 32-битных системах он, вероятно, записывал бы и в первый, и во второй слот.

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

Мне лично очень важно знать реальные проблемы, которые, вероятно, привели дизайнеров к решению в первую очередь. Но, конечно, можно было бы просто сказать "потому что разработчики языка сделали это так!" или "потому что то, что говорит спецификация языка С#": P