tags:

views:

244

answers:

9

I've seen a lot of example code written using something like (please forgive how horribly canned this is):

public class Test
{
   public object Thingy { get; private set; }
}

Unfortunately, these kinds of examples never really explain why 'set' is set as private. So, I'm just wondering if there's a good, common example that will illustrate to me why something like this would be used.

I sort of see it - the property can be run to process some extra logic in addition to setting that field. I'm just confused on how it would be invoked, and why this approach would be used rather than a generic setter method.

+16  A: 

This would be if you have a property that you don't want anyone to set but your class. This can be handy with database id's. The internal class can set it but you wouldn't want anyone else changing it. So you can give them read access but not write.

EDIT: One more point on this is that using what you showed there is helpful for automatic properties. Unfortunately with automatic properties you are unable to only specify get so to avoid exposing a setter publicly it is just made private.

EDIT: Just thought I would throw in an example. Automatic properties are great for clean, terse code. But like you showed there is a limitation in that you have to have get and set. So before it was like this for a property like you showed:

public class Test
{
   private object thingy;
   public object Thingy
   {
      get { return thingy; }
   }
}

Now we can get rid of that unneeded private declaration but it requires both. So make private to get around that.

I know this was overkill on the explanation but different things kept popping in my head.

spinon
Ah, I didn't realize that both get and set had to be declared for auto properties. That makes a lot more sense.
kevinmajor1
+3  A: 

The private makes it into a readonly property. A common example is if you have multiple classes passing around a single object, you don't want another class to be able to modify the instance.

Yuriy Faktorovich
+7  A: 

As a simple example; it is a cheap way of making an "immutable enough" object (for use in threading, state, etc). But also anywhere where the client simply shouldn't need to assign it, or can't be trusted to assign it (correctly).

Another example might be a list:

public List<Foo> Items {get;private set;}

since we might call obj.Items.Add() etc, but we would rarely assign obj.Items = .... However, this example is marred by needing explicit initialization in the constructor, and XmlSerializer hates it - to be honest for lists I mainly use:

private readonly List<Foo> items = new List<Foo>();
public List<Foo> Items {get { return items;}}

which solves both of these.

As another example, contrasting:

private readonly int foo;
public int Foo {get{return foo;}}

vs

private readonly int foo;
public int Foo {get{return foo;} private set {foo=value;}}

this pattern may be useful in serialization, for example with DataContractSerializer (with the addition of some attributes), since many serializers will still look for private accessors. This avoids us having to decorate our internal state (foo), but gives the veneer of privacy to the set.

Ultimately anything can be bypasses and assigned via reflection, so private set is only intended to avoid accidental damage to data.

Marc Gravell
Your points about the list and serializer are well taken. Thanks for that. :-)
kevinmajor1
+1! Although I'd expose generic ReadOnlyCollection or Collection rather than List - see http://blogs.msdn.com/b/codeanalysis/archive/2006/04/27/585476.aspx
TrueWill
+2  A: 

Basically, it is a readonly property. If it was written in full (not as an auto property) you would simply leave out the setter.

Two examples that are largely the same:

class Foo1
{
   public int Id { get; private set; }
   public Foo1()
   {
       Id = lastId ++;
   }
}

class Foo2
{
   private int _id;  // could be readonly 
   public int Id { get { return _id; } }
   public Foo2()
   {
       _id = lastId ++;
   }
}
Henk Holterman
+1  A: 

This syntax allows you to provide a public-facing property that appears read-only to consumers of your API but internally can be changing. By auto-implementing in this way, you avoid having to write boilerplate code such as a distinct setter or a backing field for the value, and you leave room in your design to add a bespoke set algorithm if it is deemed necessary at some point in the future without having to decide right away.

Jeff Yates
A: 

This is just laziness that comes about from auto-properties. Before auto properties were around, people would implement the getter and omit the setter for properties which are meant to be read-only.

public class Test
{
   private /*readonly*/ Type _thingy;
   public Type Thingy { get { return _thingy; } }
}

Hopefully, C# 5 will allow you to create auto-properties with a getter only - because that's what everyone wants. (They should make readonly setters in auto-props too, I need that badly)

Mark H
@Mark - if the intent is to introduce `readonly`, then fine; but as a more general "only mutable *internally* " (which is a common need) I would have to disagree; there is little benefit in having an explicit field in that case.
Marc Gravell
Yeah, introducing readonly is what I meant. I just want a syntax reduction to say `int Thingy { get; readonly set = 100; }`, or something like that.
Mark H
+1  A: 

private set is very handy for simple immutable value types.

struct Point
{
    public int X { get; private set; }
    public int Y { get; private set; }
    public Point(int x, int y)
    {
        this = default(Point);
        X = x;
        Y = y;
    }
}
Jeffrey L Whitledge
+2  A: 

I've seen this used with the design:

public class whatever
{
    public string WhateverId { get; private set; }

    public static whatever Create(string whateverId)
    {
        return new whatever() { WhateverId = whateverId };
    }
}

So you create whatever class, but after it's created the id can't be changed because it might break things that are connected to it.

the private set just gives the simple initializer syntax, I kind of like it for some scenarios.

Also can be used if it's changeable, but you need to manage it when changes are made

public void SetWhateverId(string whateverId)
{
    DisconnectAllCurrentWhateverIdReferences();
    WhateverId = whateverId;
    ReconnectAllPreviousWhateverIdReferences();
}
Jimmy Hoffa
A: 

To answer the question of a common scenario where this might be used... In an MVP pattern, if your Model exposes some properties for your Presenter I would write

public string Bazinga { get; private set; }

Now, the Model can change this value but other classes that use it cannot.

Peter Kelly