Различие между реализацией интерфейса и применением атрибута в C#

Это могло бы быть глупым вопросом, но я спрошу так или иначе,

Я читал "Демистифицированное ООП: Руководство по Самообразованию Jim Keogh и Mario Giannini" глава 11, которая касается интерфейсов. Примерами в этой книге является C++.

Я заметил, что C++ использует ISerializable для создания класса сериализуемым, который Вы реализовали бы, где как в C# Вы просто приписываете класс с [сериализуемым] атрибутом.

Каково основное отличие здесь? Случается так, что с интерфейсом необходимо обеспечить реализацию, где, как будто Вы приписываете что-то, компилятор разработает реализацию для Вас?

Я предполагаю, что с [сериализуемым] атрибутом платформа .NET использует отражение для создания сериализованного объекта из фактического объекта.

Это сказало, что действительно ли возможно в этом случае иметь [Доступный] атрибут, или использование моей теории выше привычки платформы знают, как на самом деле избавиться от объекта следовательно, необходимо ли сделать это сами?

Было бы благодарно за разъяснение.

21
задан Dmitriy 22 October 2019 в 20:42
поделиться

6 ответов

Давным-давно в далекой-далекой галактике ... Не было атрибутов или поддержки компилятора для метаданных класса, поэтому разработчики попытались реализовать свои собственный. Одним из методов, разработанных нашими предками, было объявление Marker Interfaces .

Итак, отвечая на ваш вопрос: настраиваемые атрибуты - это «эволюция» интерфейсов маркеров. Вы можете использовать оба. Но обратите внимание: если вы хотите, чтобы ваш объект реализовывал определенные методы, вы используете простой и понятный интерфейс. Вот как работает IDisposable , он заставляет вас реализовать метод с именем Dispose () . [Serializable] (и, вероятно, ISerializable в вашем примере C ++) не заставляет вас что-либо реализовывать, поскольку среда выполнения просто прочитает это объявление и выполнит свою задачу (т. Е. Сериализует объект ).

Обратите внимание, что C # также имеет интерфейс ISerializable ... Он предназначен для того, чтобы вы могли написать собственный код сериализации, который затем будет вызываться средой выполнения. Обратите внимание, что это НЕ интерфейс маркера и не замена атрибута [Serializable] , так как вам все равно нужно пометить свой класс атрибутом для работы сериализации.

11
ответ дан 29 November 2019 в 21:21
поделиться

Я думаю, вы упустили тот факт, что .NET (C #) также имеет интерфейс ISerializable:

[Serializable]
class Foo : ISerializable
{
}

Атрибут - это 'настраиваемые метаданные', интерфейс это языковая функция.

4
ответ дан 29 November 2019 в 21:21
поделиться

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

Есть и другие аспекты интерфейсов:

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

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

Тот факт, что Foo является сериализуемым, это не означает, что Bar (: Foo ) обязательно должен быть сериализуемым; поэтому приятно иметь возможность определять это на каждом уровне - хотя на самом деле я не думаю, что BinaryFormatter должен быть ключевой частью кода сериализации mots (хотя я прикусил язык).

На самом деле, если вы проверите IL, вы увидите, что [Serializable] на самом деле не записывается как атрибут - это вместо этого флаг CLI (некоторая магия компилятора). Но это не меняет факта.

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

7
ответ дан 29 November 2019 в 21:21
поделиться

Большинство атрибутов будет проверяться только во время выполнения. Некоторые из них проверяются во время компиляции (см. Условный атрибут , как указано ниже). По большей части, с атрибутом вы должны использовать отражение, чтобы увидеть, обладает ли объект им, и принять решение о том, что оттуда делать.

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

Атрибуты: http://msdn.microsoft.com/en-us/library/z0w1kczw.aspx

Интерфейсы: http://msdn.microsoft.com/en-us/library/ms173156.aspx

6
ответ дан 29 November 2019 в 21:21
поделиться

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

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

1
ответ дан 29 November 2019 в 21:21
поделиться

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

Вы должны явно предоставить BinaryFormatter право на это, по сути признавая, что объект вашего класса может быть десериализован без проблем. Вы делаете это, применяя атрибут [Serializable]. BinaryFormatter просто проверяет его наличие. Это все.

2
ответ дан 29 November 2019 в 21:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: