Пустой интерфейс для шаблона Null Object

У меня есть объект DTO для передачи данных с помощью WCF.

public class Foo
{
    //Many fields
}

Метод службы WCF возвращает этот объект, и у меня есть случай valid, когда этот объект должен быть нулевым.

Я хочу использовать шаблон нулевого объекта, чтобы возвращать что-то вместо нулевого, чтобы сделать этот код более понятным.

Итак, я реализовал это как:

public interface IFoo
{
   //empty
}


public class NoFoo : IFoo
{
   //empty
}

public class Foo : IFoo
{
    public static IFoo NoFoo { get; } = new NoFoo();

    //Many fields
}

Использование класса Foo не требует IFoo вне проверки нуля. Но я чувствую, что пустой интерфейс — это точно запах кода. Но если я добавлю все (или любые) элементы Foo в IFoo, эти элементы никогда не будут использоваться. Потому что интерфейс используется только для нулевого шаблона объекта. Вот я и не понимаю, как правильно в этой ситуации?


person nuclear sweet    schedule 11.01.2019    source источник
comment
Это называется маркерным интерфейсом, однако это все виды дубликатов.   -  person TheGeneral    schedule 11.01.2019
comment
Я знаю, как это называется, речь идет о шаблоне нулевого объекта. Так что это возможное исключение из маркера, поскольку сам нулевой объект уже нарушает некоторые правила. Вот почему я спрашиваю.   -  person nuclear sweet    schedule 11.01.2019
comment
Однако нулевой объект не означает пустой интерфейс. Это просто означает значение объекта, которое семантически эквивалентно ничего.   -  person Lasse V. Karlsen    schedule 11.01.2019
comment
Вы думали о Факультативе? Есть ли смысл в вашей проблеме?   -  person Adam Jachocki    schedule 11.01.2019


Ответы (1)


Поэтому я нахожу лучший способ добиться того, чего хочу. Я поместил Foo внутрь контейнера IResult, который реализует шаблон нулевого объекта.

public interface IResult
{
    Foo Foo { get; }
}

public class Result : IResult
{
    public static IResult NoResult = new NoResult();

    public Foo Foo { get; private set; }

    public Result(Foo foo)
    {
       Foo = foo;
    }

    private class NoResult : IResult
    {
        public Foo Foo => throw new NotImplementedException("Null object!");
    }
}
person nuclear sweet    schedule 11.01.2019
comment
Что ж, вы просто реализуете его правильно, как предлагает вики. А иначе никто, кроме вас, не мог бы догадаться о IResult обертке (вопрос был слишком абстрактным). Не могли бы вы объяснить преимущество? Я думаю, ваше решение должно иметь некоторые недостатки, например. если у вас есть переменная Foo, вы должны установить ее уродливым образом, в то время как раньше вы могли бы иметь IFoo (но, как вы говорите, если интерфейс пустой, то удобство использования такого типа довольно низкое) без необходимости приведения. - person Sinatr; 11.01.2019