property is readonly yet members are accessible - c#

Why I can implement a read-only property like so...
public IList<object> SelectedItems { get; }
...and still be able to use its members, like Add, Remove, etc. when I use the property ?
Isn't readonly supposed to be readonly "all the way down" ?

isn't readonly supposed to be readonly "all the way down" ?
This isn't a "readonly" type. It's a property where you can retrieve the value (the IList<object>), but can't set the value to a different instance of IList<object> as there is no property setter.
No. It's not readonly "all the way down" - the fact that the property only has a getter means you can get the value, but you can do anything you wish with it.
Note that I'd be careful using the term "readonly". C# has a different, distinct meaning and dedicated readonly keyword, which applies only to fields. This isn't "readonly" in the C# meaning, but a property which only provides a get operation.
If you want to have a "read only" list, a good option is to return a ReadOnlyCollection<T>. For example, if your internal class is a List<T>, you can use:
public IList<object> SelectedItems { get { return this.selected.AsReadOnly(); } }
If you are going to do this, it might be better to actually return the ReadOnlyCollection<T> as well:
public ReadOnlyCollection<object> SelectedItems { get { return this.selected.AsReadOnly(); } }
This way, users won't expect that it's safe to call .Add() on the resulting list.

Related

Should I use a field or a property?

First of all, I have read the question asking for the difference between fields and properties and I know what it is used for.
Now on to my question, I wanted to create a property where I am sure that get and set will both be empty, so I do get; set;. All good and well. But now I realised that I have just made a public field with a capital name, it is in all ways identical.
Even the argument of it being used so future code does not depend on implementation cannot be said, as I can simply make this a property and implement a getter or a setter. The semantics of a field and a property are identical outside the class it is defined in.
So my question is, should I use a field or a property when a property would simply use get;set;?
So this:
public IEnumerable<string> Products;
is identical in all ways to this:
public IEnumerable<string> Products { get; set; }
should I use a field or a property when a property would simply use get;set;?
Use a property... for the practical reasons below, and for the philosophical reasons that properties expose a state API, whereas fields expose a state implementation detail.
The semantics of a field and a property are identical outside the class it is defined in.
That's not true.
The difference is visible via reflection, which is often very important. For example, many binding frameworks won't use fields, only properties.
You can pass a mutable field by ref, but not a property - so changing a field to a property breaks source compatibility. (Code using SomeMethod(ref x.Products) will become invalid when Products becomes a property.)
Changing a field to a property also breaks binary compatibility, so if assembly X was built against assembly Y v1.0, and you change a field to a property for assembly Y v1.1, then you'd need to rebuild assembly X or it would fail to execute correctly
If you have a mutable value type (please don't do this) then writing foo.Location.X = 10 works when Location is a field (because x.Location is classified as a variable) whereas it doesn't when Location is a property (because then the expression x.Location is classified as a value). If you have a method (in your evil mutable type) which mutates the value instead, then foo.Location.DoSomething() will compile in both cases, but have a different effect. Fun for all the family.
Its depend on the situation. I'll prefer to use the property over the field. You have mentioned that public IEnumerable<string> Products; and public IEnumerable<string> Products { get; set; } are same, but in actual they are not. During compilation the property will get converted into two methods (i.e. get_Products() and set_Products()).
The advantage of property is to allows you to specify the custom code before assigning and returning the data, this is not possible with the field. Check the example below
public IEnumerable<string> Products
{
get
{
if(DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
{
//Return future product
return new List<string>();
}
else
{
// return current products
return new List<string>() { "testing" };
}
}
set
{
if (DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
{
//ignore assign product
Products = new List<string>();
}
else
{
// add assign product
Products = value;
}
}
}
Using the auto-property syntax is preferable because it creates a read/write property with a private backing field, thus allowing you to change the implementation (from a private scalar field to a dictionary entry or another backend with some other custom logic), thus freeing the "class's interface" (not the same thing as an interface) from its implementation.
Note that for collection member properties, it is advisable to make their setters private, like so:
public IEnumerable<String> Products { get; private set;}
...that way only the containing class can alter it.
Another alternative is the private readonly field, in C# 6 you can use auto-implemented properties with readonly backing fields like so:
public IEnumerable<String> Products { get; } = SomeSource.GetProducts();

Exposing interfaces instead of concrete classes

I've recently read something about using interfaces when exposing collections instead of concrete implementations (IEnumerable instead of List). I'm trying to do that now in my code. However, when I expose a property that return IEnumerable, I'm having some difficulty of not allowing nulls as a return value. Example:
public class HumanResource
{
public IEnumerable<EmployeeModel> Employees
{
get
{
// return what?
}
}
}
What should I return in the getter? I don't want to use automatic properties for this as I want to avoid nulls. What I want is to return a new collection with no items. Of course I can return any type that implements IEnumerable but how will the external user of the class know that? Or did I understand this exposing interface instead of concrete implementations wrong?
EDIT: Removed setter
Of course I can return any type that implements IEnumerable but how will the external user of the class know that?
They don't have to know that, that's exactly the point.
Your property promises to return an IEnumerable<EmplyeeModel>, and that's exactly what happens. It doesn't matter which class implementing this interface your code returns.
What I want is to return a new collection with no items.
So, Enumerable.Empty<EmplyeeModel>() or new List<EmployeeModel>() will do just fine.
When designing an API you need to think about what the consumers will do with the data types you return, and decide upon that accordingly.
Usually an IEnumerable<T> for collections suits everyone. When they want it in a list, they can do new List<T>(yourEnumerable), or yourEnumerable.ToArray() to use it as an array.
What I want is to return a new collection with no items.
Properties let you do that very easily:
public class HumanResource
{
// This is the real employees that gets returned when its not null
private IEnumerable<EmployeeModel> employees; // may be null
// This is the empty IEnumerable that gets returned when employees is null
private static readonly IEnumerable<EmployeeModel> EmptyEmployees =
new EmployeeModel[0];
public IEnumerable<EmployeeModel> Employees
{
get
{
return employees ?? EmptyEmployees;
}
set {};
}
}
The code returns an empty array when employees variable is set to null. You can set employees to a collection of any type that implements IEnumerable<EmployeeModel>, or even to an array if you prefer. This is possible because you return by interface.
The flip side of this, of course, is that the clients would have no direct access to methods of properties that are not exposed through the interface. For example, if employees is actually a List, the callers would have to use LINQ's Count() instead of obtaining .Count directly. Of course you can expose a different interface, say, IList<EmployeeModel>, to let your clients use additional methods.
You still need to provide an internal backing collection for the property in your class. You can initialize the collection in the constructor, or in the field declaration:
public class HumanResource
{
private readonly IList<EmployeeModel> _employees = new List<EmployeeModel>();
public IEnumerable<EmployeeModel> Employees
{
get
{
return _employees;
}
// No Setter - callers may only enumerate the collection
}
}
As an aside, note that even if you did use an automatic property (e.g. List<EmployeeModel>), that it would assume a default value of null, unless otherwise initialized elsewhere, so nothing changes in this respect.
Edit, Re : What are the benefits?
By removing the setter, or making it private, we prevent a caller from reassigning the internal collection of a HumanResource
By softening the collection from a List<> to an IEnumerable<>, it means the caller can only do read-only actions on the internal collection, such as to iterate it. In addition, IEnumerable<> can be used in a lazy iteration, allowing the caller to quit enumerating as soon as it has the data it needs.
As per the comment below, if the caller requires the data represented in a different collection, such as an Array, then LINQ extension methods such as .ToArray(), .ToList(), .ToDictionary() can be used. Doing so will create new collections for the caller, but with references to the same EmployeeModel objects. The performance penalties of doing this are minimal.
One final note is that there is usually no point in making the setter on an IEnumerable property private, or declaring the backing field as an IEnumerable, as this will prevent the class itself from using impure methods to manipulate the collection (i.e. add or remove objects from it), as doing so would require a cast, e.g.:
public class HumanResource
{
public IEnumerable<EmployeeModel> Employees
{
get;
private set;
}
public HumanResource()
{
// Although the property can be assigned in the CTor to prevent the null issue ...
Employees = new List<EmployeeModel>();
}
private void AddProductiveEmployee()
{
// ... We need to continually cast within the class, which is just silly.
(Employees as IList).Add(new EmployeeModel());
}
We would have the same problem with the manual backing field approach with an internal IEnumerable<>
// Unlikely to be useful
private readonly IEnumerable<EmployeeModel> _employees = new List<EmployeeModel>();
TL;DR
Use a collection type which is appropriate for the internal usage to the class (OO composition)
But on the external interfaces (e.g. public getter / property), hide the internal implementation to the minimum necessary (OO encapsulation)
Initializing the internal collection in the constructor (or inline) will prevent a null collection being exposed

Why List<T>.Add is a read mechanism in a read-only property?

Maybe it's just a misunderstanding but this is a big question for me. Let me explain it:
According to reference a property is a mechanism and not a field. A mechanism that provide read and write functions for a field, and according to this we can create a read-only, write-only or read-write property by using get and set accessors.
Now the implementation is here:
public class Foo
{
private List<string> _bar;
public List<string> Bar
{
get
{
return _bar;
}
}
public Foo()
{
_bar = new List<string>();
_bar.Add("string1");
}
}
In Foo class we have a read-only property (Bar) that consists of one string.
Now lets add a driver for this class:
static void Main(string[] args)
{
Foo fooObj = new Foo();
fooObj.Bar.Add("string2");
foreach (string s in fooObj.Bar)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
And here is the big question mark:
Why the Bar property is not read-only?
output:
srring1
string2
I know how to create a read-only collection (my question is not why List<T> is not read-only) and I need a explanation about read-only properties.
Well the Bar property is read only i.e. it can't be directly set
fooObj.Bar = new List<string>(); // compiler error
However, the data returned by that property isn't
fooObj.Bar.Add("..."); // is fine
The point to understand is the modifier on a property dictates how it can be accessed from the object, it has no direct affect on the underlying data of the property. Therefore, returning a reference type from a read-only property is the exact same as returning a reference type from a read/write property.
In your example, if you wanted the Bar to be read-only then you could return a ReadOnlyCollection<T> which is an immutable collection, rather than a List<T>.
private List<string> _bar;
...
public void Add(string item)
{
_bar.Add(item);
}
public IEnumerable<string> Bar
{
get { return new ReadOnlyCollection<string>(_bar); }
}
This would keep control of the list with the containing object but allow you to return a readonly copy of the list itself.
Okay,
A List<T> is a reference type.
So, a property
List<string> SomeList
{
get
{
// ...
}
}
is a read-only property, you cannot set the SomeList to a different List<string>. Essentially,
SomeList = new List<string>();
will not compile.
As you note, making a property of a reference type read only does not make that type read only.
If you want a read only list I'd suggest,
IReadOnlyList<string> SomeList
{
get
{
// ...
}
}
Because the getter method of your Bar property returns the list, and then you are mutating that list.Omitting the setter method only prevents you to assign a new list directly like this:
fooObj.Bar = new List<string>();
If you want to make it immutable you can change return type of your property to IEnumerable<string> instead.. Though you can still cast it to list and then mutate...
The Bar property is read-only. You can only read the list Bar points to - you cannot make Bar point to some other list.
However, the list itself is mutable. You can add or remove items from it.
Eric lippert calls this "shallow immutability" in his blog post Immutability in C# Part One: Kinds of Immutability. The property is read-only, but its contents can change.

Why am I getting error: "cannot implicitly convert type System.Collections.Generic.List"

I have the following sealed class. I'm trying to return the list as a ReadOnlyCollection. Tried a couple of things but I'm not getting the hang of this. So how do I return or cast the list to the readonly collection?
public sealed class UserValues
{
private readonly List<UserValue> _Values = new List<UserValue>();
public ReadOnlyCollection<UserValues> Values
{
get
{
return _Values;
}
}
}
You're getting the compile-time error because a List<UserValue> is not a ReadOnlyCollection<UserValue>, nor is it implicitly convertible to that. (I assume you meant ReadOnlyCollection<UserValue> instead of ReadOnlyCollection<UserValues> by the way?)
It's probably simplest to use List<T>.AsReadOnly - but you might as well only create it once:
public sealed class UserValues
{
private readonly List<UserValue> values = new List<UserValue>();
private readonly ReadOnlyCollection<UserValue> valuesView;
public UserValues()
{
valuesView = values.AsReadOnly();
}
public ReadOnlyCollection<UserValues> Values { get { return valuesView; } }
}
The ReadOnlyCollection<T> really is just a view - so changes to the underlying collection will be visible through the view.
Try:
return new ReadOnlyCollection<UserValue>(_Values);
Edit:
Given what you've said to Jon, your code doesn't make sense. Your get is referencing a type of List<UserValue>, but you're wanting to convert it to a type of ReadOnlyCollection<UserValues>, which cant be done - that's 2 collections of 2 different types.
We'll need more information to help you answer this question. Are you wanting your UserValues class to return a collection of UserValues types, or a collection of UserValue types? Your code implies UserValue, but your follow on comments state UserValues. Are you sure your supervisor didn't make a typo?
If not, you'll need some internal collection like so:
private readonly List<UserValues> _MoreValues = new List<UserValues>();
And then return that, in the syntax that I (or others who have answered - all the answers given are valid for converting a List to a ReadOnlyCollection) have shown.
Note that my code compiles targeting .Net 3.5, presuming that the types are compatible (meaning ReadOnlyCollection<UserValue> wraps List<UserValue>, or both are UserValues).
_Values is a List<UserValue>, not a ReadOnlyCollection<UserValue> (they're not related, as far as the compiler knows), so you can't return _Values directly. You can either create a ReadOnlyCollection<T> from your list and return that, like:
private List<UserValue> _Values = [whatever];
private ReadOnlyCollection<UserValue> _ValuesWrapper;
public UserValues()
{
_ValuesWrapper = _Values.AsReadOnly();
}
public ReadOnlyCollection<UserValue> Values
{
get { return _ValuesWrapper; }
}
...or, if you're just looking for a read-only way of accessing your collection and don't need a ReadOnlyCollection<UserValue> object specifically, you could change your property to return a read-only interface that List<T> implements, and your application could use that instead. .NET 4.5 introduced some read-only collection interfaces that are great for this kind of thing:
public IReadOnlyList<UserValue> Values
{
get { return _Values; }
}

Can pointers be used with Dictionary<TKey,TSource>?

Let's say I have the following class:
public class MyClass {
public string FirstAttribute {
get {
return Attributes["FirstAttribute"];
}
set {
Attributes["FirstAttribute"] = value;
}
}
public string SecondAttribute {
get {
return Attributes["SecondAttribute"];
}
set {
Attributes["SecondAttribute"] = value;
}
}
public Dictionary<string, string> Attributes;
public MyClass(Dictionary<string,string> att) {
Attributes = att;
}
}
and I wanted to be able to obtain a pointer to the value that is stored in the Dictionary, so that I can get and set the values (yes unsafe) directly without having to wait for the Dictionary to search for the element by key every time.
Is there a way to do that in c#?
No, I don't believe so. You could store a mutable wrapper in the dictionary though:
public class Wrapper<T>
{
public T Value { get; set; }
}
Then create the dictionary (which should be private, by the way - public fields are a really bad idea other than for constants) as a Dictionary<string, Wrapper<string>>. You can then keep fields for the Wrapper<string> objects associated with "FirstAttribute" and "SecondAttribute".
Frankly I don't think this would be a particularly good idea - I'd just stick with the dictionary lookup - but it's an option. (Assuming nothing's going to change which wrapper is associated with the keys.)
Another option is simply to use fields for the two specific attributes - when you're asked to set a new value, set it in the dictionary and set a field. When you're asked for the current value, just return the value from the field. Of course, that's assuming that you're in control of the dictionary (i.e. so it can't change outside your class).
No, no, no, no.
strings are immutable for a reason. A string might be shared between multiple references: modifying it directly with unsafe code might lead to weird behavior.
A way to go around this would be to write a wrapper class that olds your value, and keep a reference to an instance of that wrapper. The getters and setters would then modify the wrapper's property.
If the values in the dictionary were mutable, you could grab the reference to them and mutate them. But strings are immutable. So the dictionary has its own copy of a reference to your string, and you can't alter the string it is pointing to. If you try to replace it with another string, you need to update the dictionary with the new reference. So basically there's no way to improve on what you have in this situation.

Categories