#c#
#c#
Вопрос:
У меня есть следующий интерфейс:
public interface IReport
{
int ReportId {get; set;}
}
У меня есть объект, который имеет свойство identity column:
public int PaymentReportId {get; set;}
Мне нужно PaymentReport
реализовать IReport
Внутри моего PaymentReport.cs я сделал:
public int PaymentReportId {get; set;}
public int ReportId {
get => PaymentReportId;
set {} //no need to ever set this;
}
В противном случае компилятор жаловался на то, что установщик не реализован.
Есть ли более чистый способ сделать это?
Комментарии:
1. Интерфейс обещает, что свойство может быть установлено, и все же ваш класс нарушает это обещание. Удалите установщик из интерфейса, если вы собираетесь реализовать свойства, доступные только для чтения
2. Если вы собираетесь иметь некоторые классы только для чтения и некоторые классы get / set, вам нужны разные интерфейсы или свойства для каждого из них.
3. Посмотрите на принцип разделения интерфейса…
4. @Karol Skrobot: Я не задал очевидный вопрос. Вам действительно нужно
PaymentReportId
свойство? РазвеReportId
свойства недостаточно?
Ответ №1:
Если вы пытаетесь придерживаться SOLID, существует принцип, называемый разделением интерфейса.
Принцип разделения интерфейса (ISP) гласит, что ни один клиент не должен быть вынужден зависеть от методов, которые он не использует.
При вашем подходе принцип явно нарушается, поскольку у класса PaymentReport
есть параметр установки свойств, который, по сути, не нужен.
Подумайте о том, чтобы разделить IReport
на IReportRead
и IReportWrite
и реализовать только то, что необходимо.
public interface IReportRead
{
int ReportId { get; }
}
public interface IReportWrite
{
int ReportId { set; }
}
public class PaymentReport : IReportRead {//...}
Таким образом, у вас есть четкая абстракция, и вы не загрязняете реализацию.
Ответ №2:
Я удалил набор из ReportId iReport, а затем внедрил в классе.
public interface IReport
{
int ReportId { get; }
}
public class PaymentReport : IReport
{
public int PaymentReportId { get; set; }
public int ReportId
{
get => PaymentReportId;
}
}
Комментарии:
1. @MaximilianAst приношу свои извинения, я не объяснил. Предоставлено больше разъяснений.
Ответ №3:
Как говорили другие, самым чистым было бы изменить интерфейс или разделить на несколько интерфейсов. Вот пример разделения интерфейса на два и использования их как в get
сценарии, так и в get, set
scenario:
interface IFooGet
{
int Id { get; }
}
interface IFooSet
{
int Id { set; }
}
public class FooGet : IFooGet
{
public int Id { get; }
}
public class FooGetSet : IFooGet, IFooSet
{
public int Id { get; set; }
}
Если это невозможно (возможно, у вас нет кода для интерфейса?) вы можете выдать исключение, если кто-то попытается вызвать свойство.
class PaymentReport : IReport
{
public int PaymentReportId {get; set;}
public int ReportId {
get => PaymentReportId;
set => throw new NotSupportedException();
}
}
Простое наличие пустого тела в set
может иногда приводить к скрытию ошибки https://en.wikipedia.org/wiki/Error_hiding если какой-то код в будущем попытается вызвать setter и сделает предположение, что setter действительно делает что-то значимое