Understanding Private Setters

Why private setter?

If you use an auto property, you don't see the background field:

public int Counter { get; private set; }

This allows you to have it private for set and public for get, without having to write the backing field yourself.

Even if you're using a backing field, there are times when you want to still use the property, and not the field. A property setter can actually include other logic (validation/change notification/etc) which may be appropriate to call, but you may want to restrict the access to this to your class.

why to have private setter in entity

You don't ever need to set primary column value yourself, exactly because it's autogenerated by database, so why allow to do things that do not make sense? Hence you make Id setter private. EF can still set this property when materializing object, even though it is private.

Same story with constructor. EF requires your entity to have parameterless constructor, but it can be private. But you don't want (in your example) for entity to be created by user without providing first and last names, because most likely those names are required and you want unavoidably express this intention. So you have one constructor for you to create entity (with both names set) and one for EF to materialize object received from database (parameterless one).

Note that both private setter and this configuration of constructors are in no way required by EF. All this is done for developer convenience to prevent undesired behavior (setting Id field or crearing Emp entity without providing names).

Why private setter?

If you use an auto property, you don't see the background field:

public int Counter { get; private set; }

This allows you to have it private for set and public for get, without having to write the backing field yourself.

Even if you're using a backing field, there are times when you want to still use the property, and not the field. A property setter can actually include other logic (validation/change notification/etc) which may be appropriate to call, but you may want to restrict the access to this to your class.

C# - Using a private setter with a public getter on reference types

If the type you're referring to is mutable, then yes, anyone with a reference to the "container" can fetch a reference and then mutate the object. For example:

using System;
using System.Collections.Generic;

class Container
{
public List<string> List { get; private set; }
= new List<string>();
}

class Program
{
static void Main()
{
var container = new Container();
var list = container.List;
Console.WriteLine(list.Count); //0

container.List.Add("foo");
Console.WriteLine(list.Count); // 1
}
}

Here the List<string> is being mutated outside Container. One option to avoid this would be to use a read-only view over the mutable data:

using System;
using System.Collections.Generic;

class Container
{
private readonly List<string> list = new List<string>();

public IReadOnlyList<string> ListView { get; }

public Container()
{
ListView = list.AsReadOnly();
}

public void AddItem(string item)
{
list.Add(item);
}
}

class Program
{
static void Main()
{
var container = new Container();
Console.WriteLine(container.ListView.Count); //0

// container.ListView.Add("foo"); // Compile-time error

container.AddItem("foo");
Console.WriteLine(container.ListView.Count); // 1
}
}

Note that you shouldn't just return the list directly from the property, even if the compile-time type is IReadOnlyList<T> - because then a caller could just cast back to List<T> and mutate it. List<T>.AsReadOnly() returns a genuinely read-only wrapper object around the list, so callers really won't be able to mutate it.

Omitted setter vs private setter?

In C# 6, get; only properties are only settable from the constructor. From everywhere else, it is read-only.

A property with a private set; can be set from everywhere inside that class.

Testing properties with private setters

This works out of the box if you're using Moq (which the question is tagged with, so I assume you are):

var mockAddress = new Mock<Address>();
mockAddress.SetupGet(p => p.District).Returns("Whatever you want to match");

So a more complete example is:

var mockAddress = new Mock<Address>();
mockAddress.SetupGet(p => p.Id).Returns(42);
mockAddress.SetupGet(p => p.District).Returns("What you want to match");

var mockAddressRepository = new Mock<IRepository<Address>>();
var addresses = new List<Address> { mockAddress.Object };
mockAddressRepository.Setup(p => p.GetEnumerator()).Returns(addresses.GetEnumerator());

var addressToMatch = mockAddressRepository.Object.FirstOrDefault(address => address.Id == 42);
Console.WriteLine(addressToMatch.District);

This outputs the expected value:

What you want to match

Private setter typescript?

The TypeScript specification (8.4.3) says...

Accessors for the same member name must specify the same accessibility

So you have to choose a suitable alternative. Here are two options for you:

You can just not have a setter, which means only the Test class is able to set the property. You can place a breakpoint on the line this._prop =....

class Test
{
private _prop: string;
public get prop() : string
{
return this._prop;
}

doSomething() {
this._prop = 'I can set it!';
}
}

var test = new Test();

test._prop = 'I cannot!';

Probably the ideal way to ensure private access results in something akin to a "notify property changed" pattern can be implemented is to have a pair of private get/set property accessors, and a separate public get property accessor.

You still need to be cautious about someone later adding a direct call to the backing field. You could get creative in that area to try and make it less likely.

class Test
{
private _nameBackingField: string;

private get _name() : string
{
return this._nameBackingField;
}

private set _name(val: string)
{
this._nameBackingField = val;
// other actions... notify the property has changed etc
}

public get name(): string {
return this._name;
}

doSomething() {
this._name += 'Additional Stuff';
}
}

What's the difference between a property with a private setter and a property with no setter?

As you can see in your second sample, you can leave out the implementation for a property. .NET will then automatically create a local variable for the property and implement simple getting and setting.

public int MyProperty { get; private set; }

is actually equivalent to

private int _myProperty;

public int MyProperty {
get { return _myProperty; }
private set { _myProperty = value; }
}

Writing

public int MyProperty { get; }

does not work at all, as automatic properties need to implement a getter and a setter, while

public int MyProperty { get; private set; }

leaves you with a property that may return any int, but can only be changed within the current class.

public int MyProperty { get { ... } }

creates a read-only property.

Question is: what do you need? If you already have a member variable that's used within your class and you only want to return the current value using a property, you're perfectly fine with

public int MyProperty { get { return ...; }}

However, if you want a read-only property, which you need to set within your code (but not from other classes) without explicitly declaring a member variable, you have to go with the private set approach.

Why use private property setters since member variables can be accessed directly?

A setter can implement other behaviour/logic when a property is updated, so that you don't have to manually implement it at every location where a property might be updated.

It can:

  • automatically update other fields
  • Validate the new value (eg. ensure an email address matches a regular expression)
  • To keep code that needs to be run every time a field is updated in one place

For example:

private string _myField;
private int _myField_num_updated;
private DateTime _myField_updated_at;

public string MyProperty
{
get { return _myField; }
private set {
_myField = value;
_myField_num_updated++;
_myField_updated_at = DateTime.Now;
}
}


Related Topics



Leave a reply



Submit