21

I came across an interface recently that only defined a setter like so:

public interface IAggregationView
{
   DataTable SetSiteData { set; }
}

I queried this, and it is believed that this is one of the practices advocated by Microsoft for WebPart design (for SharePoint). In fact this example is directly copied from their examples.

I see this as a bad pattern, I don't see why someone should be able to set a value, and then not be able to read it again, and I believe a setter should always be accompanied with a getter (but not necessarily the other way around).

I'm wondering if anyone can explain the benefit of only having a setter, why Microsoft might be suggesting it in this case, and if it's really a good pattern to be following?

pnuts
  • 58,317
  • 11
  • 87
  • 139
Ian
  • 33,605
  • 26
  • 118
  • 198
  • I would guess it's the same as not providing a setter. The setter in that case is private set by default. Probably the same for the getter too. – Jamie Dixon Sep 17 '12 at 08:51
  • 4
    If not duplicate then may be related: http://stackoverflow.com/questions/4695551/write-only-properties-whats-the-point – Habib Sep 17 '12 at 08:52
  • 1
    It is an unusual pattern, certainly; as is naming a property with a `Set...` prefix. – Marc Gravell Sep 17 '12 at 08:54
  • It's useless. Even MSDN documentation states one should not use them. http://msdn.microsoft.com/en-us/library/ms229006.aspx – danish Sep 17 '12 at 08:55
  • @Habib: Thanks Habib, indeed it is related and I'll have a read of that. I think this goes a bit further because I'd like to know why Microsoft have suggested it in this case. – Ian Sep 17 '12 at 08:59
  • This is not a write-only property. So not a dupe. – H H Sep 17 '12 at 09:17
  • @danish Useless is subjective. The setter only property could as well have been a `public void SetProperty(PropertyType value)` but maybe properties setters are more desired in a particular situation then using methods when it comes to reflection. As a property setter has only 1 parameter, the value. As where methods can have more than 1 parameter. I wouldn't state this as useless. I do think it is unusual and there must be a good reason if you want to use it. – Mike de Klerk Jun 30 '17 at 09:06

5 Answers5

24

There are two scenarios I can see where this might be reasonable:

  1. it is not possible get the value, for example a password; however, I would replace that with a void SetPassword(string) method, personally
  2. the API it is designed for has no requirement to ever read the value, and it is being restricted purely to expose the minimum required API

Re my first point, a Set... method may not be ideal if the consuming API is essentially an automated mapper that assigns values to properties; in that scenario properties would indeed be preferable.

Re your "I don't see why someone should be able to set a value, and then not be able to read it again" - by the same point, however, it could be argued that someone setting the value already knows the value (they set it), so they have no requirement to do this.

But yes; it is very unusual to have a set-only property.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I like your password example actually, that is a good clear case of where you might want to do this, but personally would also opt for a method. Nice answer. – Ian Sep 17 '12 at 09:00
  • If you expect at least some implementing classes to optionally add a getter, then it makes sense to have it as a setter instead of a `SetFoo` method. Interfaces don't stand alone, they represent a common subset of the operations on a family of classes. So you have to look at the extant classes, as well as the code that consumes the interfaces, to decide if the interface design makes sense. – Daniel Earwicker Sep 17 '12 at 09:07
  • @DanielEarwicker yes, but when the interface API isn't a direct subset of the class's public API, there's always *explicit interface implementation* – Marc Gravell Sep 17 '12 at 09:08
  • I agree, there *is* a more complicated way to achieve the same thing. :) – Daniel Earwicker Sep 17 '12 at 09:09
15

The role of get and set in interface properties is slightly different from those in classes.

public interface IAggregationView
{
   DataTable SetSiteData { set; }
}

class AggregationViewImp : IAggregationView
{
   public DataTable SetSiteData { get; set; }  // perfectly OK
}

The interface specifies that the property should at least have a public setter. The definition and accessibility of the getter is left to the implementing class.

So if the interface contract only needs to write, get can be left open. No need to demand a public getter.

As a consequence, you cannot really specify a read-only property in interfaces either. Only 'at least read access'.

interface IFoo
{
    int Id { get;  }
}

class Foo : IFoo
{
    public int Id { get; set; }  // protected/private set is OK too
}
H H
  • 263,252
  • 30
  • 330
  • 514
  • Equally importantly "Foo" is *internal* thus properly encapsulating the implementation inside its immediate scope. –  Sep 18 '12 at 14:07
5

I can imagine using it for (manual) dependency injection. A class may need to have a collaborator injected that it only uses internally. Of course one would normally choose to do this in the class' constructor, but there may be times when one would wish to change the collaborator at runtime.

KaptajnKold
  • 10,638
  • 10
  • 41
  • 56
2

Classes that implement the interface may add a getter. Most uses of the property may be via an implementing class, not via the interface itself. In which case most code has the ability to get and set the property. The only reason for the interface may be that there is some common code that accesses a common subset of the methods/properties of a family of classes. That code only requires the setter, not the getter. The interface documents that fact.

An interface is just a facility for declaring a group of operations that are "atomically needed" (e.g. if you need to call method A, you'll need to read property B and set property C).

So as always, it depends.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
1

In my experiences such interfaces crop up due to some special need, not for architectural reasons. For example in ASP.NET applications people sometimes make the Global.asax generated type derive from such an interface when they want to maintain global state. Someone might create an initialization value in a separate part of the application and need to publish it to a global place.

I usually like to replace a set-only property with a SetXxx method and make the method check that it is called at most once. That way I clearly enforce "initialization style" which is much less of a smell (imho).

Certainly one cannot set to never produce such a thing but it is to be avoided and will certainly raise questions during code review.

usr
  • 168,620
  • 35
  • 240
  • 369