9

I have some C# code that loves to create properties that have setters but no getters. To me this seems like an anti-pattern, but am I missing something?

public List<SiteVisitSummary> DataSource {
    set {
        // crazy logic here 
    }
}
kelloti
  • 8,705
  • 5
  • 46
  • 82

7 Answers7

21

I don't know if I'd call it an anti-pattern or not. I think the important thing to realize is that the property in your example is essentially a method, disguised as a property. For this reason it's unintuitive, and I'd generally avoid it. To me this looks a lot more natural:

public void SetDataSource(IEnumerable<SiteVisitSummary> dataSource)
{
    // crazy logic here
}

One fairly reasonable case I have seen made for set-only properties is when there are several properties grouped together such that setting all to a single value is a reasonable thing to do (but obviously, getting all as one value doesn't make sense). For example:

class Polyhedron
{
    public int Height { get; set; }
    public int Width { get; set; }
    public int Depth { get; set; }

    public int AllDimensions
    {
        set { Height = Width = Depth = value; }
    }
}
Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • 4
    So if it's unintuitive and generally unuseful, wouldn't that make it an anti-pattern? – kelloti Dec 30 '10 at 17:58
  • 1
    @kelloti: I could agree with *generally* not useful; but I did give an example of a case where I believe it makes some sense. So I wouldn't make the blanket statement that it's an anti-pattern in all cases. – Dan Tao Dec 30 '10 at 18:00
  • Yeah, I would use a method for that though. Still goofy – Ed S. Dec 30 '10 at 18:04
  • 4
    +1 for the example, but I disagree that this should be a property. It makes no sense as a property even in this case. – kelloti Dec 30 '10 at 18:05
  • 1
    @Ed, @kelloti: I'll be completely honest with you: I would make it a method too. But I think to say it makes "no sense" is pretty subjective. A common way of viewing properties vs. methods is that (among other distinctions) properties are cheap and methods are less cheap. You *could* argue, at least, that making `AllDimensions` a property in the example above conveys the message that it is a very cheap operation. `SetAllDimensions()`, in contrast, *might* be expected by some to be more expensive. Again, I personally wouldn't make it a property either—just playing devil's advocate. – Dan Tao Dec 30 '10 at 18:17
  • 14
    I think it makes more sense as a property than a method; you can use it in an object initializer list this way. – Jimmy Jan 14 '11 at 21:11
  • @Jimmy: Nice one—+1 to that comment for thinking outside the box (outside the box *I* think in, anyway). – Dan Tao Jan 14 '11 at 21:22
  • 8
    and what would be the behavior of new Polyhedron { Width = 10, AllDimensions = 5 } ?? Also I expect that Height and Depth initialize at it's own default value, what actually isn't. I don't like when code doesn't act as one should expect. – Bart Calixto May 19 '14 at 19:10
  • To be fair, this class should be a `Cube` and the setters should be `private`. Otherwise, *very* interesting example. – AustinWBryan Jun 06 '18 at 08:23
6

It could be useful for Dependency Injection, where instead of using a constructor for the injection you are using properties.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Aaron McIver
  • 24,527
  • 5
  • 59
  • 88
  • I don't get what you mean, could you clarify? Also - it's not used for DI – kelloti Dec 30 '10 at 17:53
  • 1
    @kelloti Added reference to DI – Aaron McIver Dec 30 '10 at 17:58
  • I know what DI is, but I can't think of a non-kludgy way to use a set-only property with DI – kelloti Dec 30 '10 at 17:59
  • 1
    @kelloti The only reason I could gather is that you do not have your reference at instantiation time and can not use the constructor for injection and want to inject it downstream for testing purposes perhaps...the property itself would remain as such with only a setter since the getter would have no immediate value as you are simply trying to seed the object... – Aaron McIver Dec 30 '10 at 18:09
  • fair enough, I guess that might work – kelloti Dec 30 '10 at 18:13
  • That is exactly the reason I started to google set only properties :) Di where I do not have the property at constructor time (not all code is moved to full DI yet) – John Demetriou Dec 08 '17 at 14:37
2

I don't see anything inherently bad about the practice, although it doesn't make much sense to me.

The point of encapsulation is to limit what can change the state of an object so that the state becomes easier to maintain. I can't think of any good reason to make a property write-only. And, if I could, it might more sense to make it a method instead.

Users are accustomed to being able to read properties and they may waste time wondering why the heck your property is so weird.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
1

Not bad practice as such, just not very useful (a property that you can't read?).

Oded
  • 489,969
  • 99
  • 883
  • 1,009
1

If you are expecting much logic to happen, it would seem much clearer of the cost by using a method to set that.

Cort
  • 237
  • 2
  • 11
1

This may not be everyone's cup of tea, but I posted an answer to another question where I demonstrated the use of an "infuser" concept, in this case a struct nested inside of an immutable struct. The infuser has write-only properties that complement the read-only properties of the immutable type.

To be fair, I agree that this approach might be confusing and I would think twice before including code like this in an application that is not just a hobby project.

The concept can also be useful for normal classes, not just immutable types. It allows the code that is responsible for instantiating an object to have read/write access to the data contained within that object. Then the object can be passed off to other code, which has read-only access to the data within the object.

Community
  • 1
  • 1
Dr. Wily's Apprentice
  • 10,212
  • 1
  • 25
  • 27
  • I'd like to add the constraint that it should be a non-kludgy reason to use set-only properties – kelloti Dec 30 '10 at 19:12
  • Hmm. Well, as I said, it's not everyone's cup of tea. I really don't consider it a kludge, though. I see it as a possible design choice to control what code has write-access to the object. Set-only properties are a possible way to implement such design choices. – Dr. Wily's Apprentice Dec 30 '10 at 19:20
0

It's kind of a weird thing really. Why would you write an API that allows the user to set a list but not read it? How about returning a ReadOnlyCollection instead and exposing the property as an IList instead of a List?

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • This reminds me of the `DataRow.ItemArray` property, which is typed as `object[]` and (surprisingly) has a setter. It is confusing because calling `ItemArray[0] = 5` does nothing; the property is really two methods (one that copies internal contents into an array, one that copies an input array back to internal contents). This is a case where I could imagine having a set-only method that accepts a collection *might* have made sense. – Dan Tao Dec 30 '10 at 17:58
  • Yeah, but in this case the assignment would be a compilation error. Of course, a ReadOnlyCollection wouldn't modify someone from changes the *properties* of objects stored in it. – Ed S. Dec 30 '10 at 18:03