1

following the example:

interface ISomeInterface
{
    string SomeProperty { get; }
}

I have the implementation that compiles:

public class SomeClass : ISomeInterface
{
    public string SomeProperty
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
 }

which is a problem. How do I make the interface a contract that, won't allow set in it's implementation?

notice: I'm not looking for a solution how to avoid set IN the implementation but in the interface that will validate it from any new implementation, thanks.

Franz Wimmer
  • 1,477
  • 3
  • 20
  • 38
RollRoll
  • 8,133
  • 20
  • 76
  • 135

4 Answers4

4

Interfaces only specify what MUST be implemented, but do not restrict what other methods, or properties may also be implemented.

So the get is the only thing that you have specified.

Since you are silent on the set, any implementer of the interface is at liberty to add or not to add the set.

In short, with an interface specification you cannot do what you want to do.

Jens Meinecke
  • 2,904
  • 17
  • 20
3

If you want to make sure the set is never called then you could always cast the instance to the Interface

If you really need to make sure there is no set you could use an abstract class instead of an interface

abstract class SomeInterface
{
   virtual string SomeProperty { get; }
}
Mike Norgate
  • 2,393
  • 3
  • 24
  • 45
2

Based on Mike answer, you could write something like that :

public interface ISomeInterface
{
    string SomeProperty { get; }
}

public abstract class SomeInterfaceBase : ISomeInterface
{
    public abstract string SomeProperty { get; }
}

So you can define your class like that:

public class SomeClass : SomeInterfaceBase
{
    public override string SomeProperty { get; }
}

If you try to implement a setter, it will not compile.

Thomas
  • 24,234
  • 6
  • 81
  • 125
1

Having a setter isn't an issue. The reason for this is because of how we treat interfaces.

Whether the concrete class has a setter or not does not matter, because we are supposed to treat the object as an ISomeInterface. In this case it only has a setter.

For instance lets take a factory method:

class Program
{
    interface ISomeInterface
    {
        string SomeProperty { get; }
    }

    static ISomeInterface CreateSomeClass()
    {
        return new SomeClass();
    }

    class SomeClass : ISomeInterface
    {
        public string SomeProperty
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }

    static void Main(string[] args)
    {
        ISomeInterface someInterface = CreateSomeClass();
        someInterface.SomeProperty = "test"; //Wont compile
    }
}

The class's implementation of a setter is meaningless, because we are only interested in treating the object as ISomeInterface. Interfaces are additive. In other words, they define a contract of what needs to be defined, rather than what should not.

If I was to treat it in any other way, it would be something like this:

    ((SomeClass) someInterface).SomeProperty = "test"; //Code smell

which I would consider a code smell, because it's assuming that someInterface is SomeClass (treating interfaces as concrete classes)

Serguei Fedorov
  • 7,763
  • 9
  • 63
  • 94