Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private 'set' in C# - having trouble wrapping my brain around it

Tags:

c#

private

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.

like image 212
Major Productions Avatar asked Jul 22 '10 20:07

Major Productions


People also ask

What is private set in C?

Private setters allow you to create read-only public or protected properties. That's it.

What is get private set in C#?

The meaning of Encapsulation, is to make sure that "sensitive" data is hidden from users. To achieve this, you must: declare fields/variables as private. provide public get and set methods, through properties, to access and update the value of a private field.

Can getters and setters be private?

The reason for declaring the getters and setters private is to make the corresponding part of the object's abstract state (i.e. the values) private. That's largely independent of the decision to use getters and setters or not to hide the implementation types, prevent direct access, etc.

Can properties be private?

Properties can be marked as public , private , protected , internal , protected internal , or private protected . These access modifiers define how users of the class can access the property.


7 Answers

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.

like image 111
spinon Avatar answered Oct 08 '22 05:10

spinon


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.

like image 26
Marc Gravell Avatar answered Oct 08 '22 04:10

Marc Gravell


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.

like image 20
Yuriy Faktorovich Avatar answered Oct 08 '22 04:10

Yuriy Faktorovich


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;   
   public int Id { get { return _id; } }
   public Foo2()
   {
       _id = lastId ++;
   }
}
like image 20
Henk Holterman Avatar answered Oct 08 '22 05:10

Henk Holterman


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();
}
like image 40
Jimmy Hoffa Avatar answered Oct 08 '22 06:10

Jimmy Hoffa


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.

like image 32
Jeff Yates Avatar answered Oct 08 '22 06:10

Jeff Yates


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;
    }
}
like image 30
Jeffrey L Whitledge Avatar answered Oct 08 '22 06:10

Jeffrey L Whitledge