Ответ
Нет, интерфейсы в C# не могут содержать поля экземпляра (instance fields). Они определяют контракт — набор членов, которые реализующий класс должен предоставить, а поля относятся к внутренней реализации.
Что может содержать интерфейс:
- Методы (включая методы расширения)
- Свойства (автореализуемые или с явными get/set-аксессорами)
- События (
event) - Индексаторы (
this[])
Пример допустимого содержимого интерфейса:
public interface ILoggable
{
// Свойство — это допустимо (по сути, методы get/set).
string Id { get; }
// Метод — это допустимо.
void Log(string message);
// Событие — это допустимо.
event EventHandler OnLogged;
// Статическое поле/константа — допустимо (начиная с C# 8.0).
static readonly string DefaultCategory = "General";
const int MaxEntries = 1000;
}
Почему поля недопустимы? Поле — это данные. Разрешение полей в интерфейсе означало бы навязывание конкретной реализации хранения данных, что нарушает принцип абстракции. Если вам нужно обязать реализующий класс иметь определенное поле, используйте абстрактный класс.
// Абстрактный класс МОЖЕТ содержать поля.
abstract class AbstractExample
{
protected int _value; // Поле — допустимо.
}
Важно: Начиная с C# 8.0, интерфейсы поддерживают статические члены, включая статические поля и методы, но это по-прежнему не поля экземпляра.
Ответ 18+ 🔞
Да ты что, серьёзно? Ну блядь, вот сидишь такой, думаешь: "Сейчас я накидаю в интерфейс полей, и все классы будут их таскать, красота!" А нихуя! Нельзя так, нахуй!
Интерфейс в C# — это как договор, понимаешь? Контракт, ёпта. Ты обязуешься реализовать определённые штуки, а как ты это сделаешь внутри — твои проблемы. А поля — это уже внутренняя кухня, данные, состояние объекта. Это как если бы в договоре на поставку пива тебе ещё и холодильник в придачу прописывали — нихуя не гибко.
Что же можно в интерфейс пихнуть, спросишь? Да нормальные вещи:
- Методы (ну это святое).
- Свойства (это по сути те же методы
get/set, так что ок). - События (
event— тоже окей). - Индексаторы (
this[]— да и такое бывает).
Вот, смотри, как выглядит приличный интерфейс:
public interface ILoggable
{
// Свойство — можно, это ж по факту геттер.
string Id { get; }
// Метод — можно, это основа основ.
void Log(string message);
// Событие — можно, почему бы и нет.
event EventHandler OnLogged;
// Статическое поле или константа — можно (с C# 8.0).
static readonly string DefaultCategory = "General";
const int MaxEntries = 1000;
}
Видишь? Ни одного обычного поля экземпляра! Потому что если разрешить поля, то это уже будет не абстракция, а диктат, блядь. "Храни данные вот так!" — а если классу это неудобно? Пиздец тогда.
Так что же делать, если очень хочется обязать класс иметь поле? Да используй абстрактный класс, ебать! Он для этого и придуман.
// А вот абстрактный класс — другое дело, тут поля пожалуйста.
abstract class AbstractExample
{
protected int _value; // Поле — да на здоровье, хуле.
}
Вот и вся магия. Интерфейс — про поведение, про "что можно сделать". Абстрактный класс — уже ближе к реализации, к "из чего это сделано". Не путай, а то получишь компилятор по ебалу.