I know how to use properties and I understand that they implicitly call underlying get and set accessors, depending on whether we are writing to or reading from a property.
static void Main(string[] args)
{
A a = new A();
(a.b).i = 100;
}
class A
{
private B _b = new B();
public B b
{
get { return _b; }
}
}
class B
{
public int i;
}
What code (a.b).i = 100; essentially does is that first property’s get accessor returns a reference to an object _b, and once we have this reference, we are able to access _b’s members and change their values.
Thus, in our example, having read only property only prevents outside code from changing the value of a reference variable _b, but it doesn’t prevent outside code from accessing _b’s members.
So it seems that property can only detect whether we are trying to read from or write to a variable ( in our case variable _b ) located on the stack, while it’s not able to detect whether we’re trying to also write to members of an object to which the variable on the stack ( assuming this variable is of reference type ) points to.
a) But doesn’t that defeat the whole purpose of having read-only properties? Wouldn’t it be more effective if properties had the ability to also detect whether we’re trying to access members of an object returned by get accessor( assuming backing field is of a reference type )?
thank you
Immutability is not transitive; you can't expect mutable objects into an immutable accessor to be immutable.
Your reference is read only, not your object.
Imagine a class like this:
public class A
{
private List<int> _myList<int> = new List<int>();
public List<int> MyList { get { return _myList; } }
}
Now, users of the class can add and remove and access items in the list, but they cannot replace the list itself. This is important. It allows you to do things inside the class like assume the _myList member is never null, for example.
Put a more general way, this paradigm allows you do define an interface into your class such that users can use the types in the properties you expose, but they cannot just swap instances of complex types out from under you.
No, it does not defeat the purpose of read-only properties.
It is possible to use read-only properties that don't let the user change the underlying data. For example, you can have your property return a System.Collections.ObjectModel.ReadOnlyCollection even though the underlying type is a List. This, of course, won't prevent the user from changing the properties of the items in the collection.
Of course you can access B.i; it's public. You're thinking that since _b is private, all methods should be private when fetched through A? In that case it's pretty useless as you wouldn't be able to use B for anything.
You ask:
Doesn’t that defeat the whole purpose
of having read-only properties?
But look: your B.i member is a public field.
I ask you, then: what is the purpose of having a public field? It only makes sense if you want users of your code to be able to change that field's value. If you don't want that, it should be a private field, or (if you want to provide read but not write access) a property with a private set accessor.
So there's your answer. private B _b serves its purpose in the code you posted quite well (_b cannot be externally set to something new), just as public int i serves its purpose equally well (i can be externally changed).
Reference immutability is a popular feature request. Too bad its is so dramatically non CLS compliant. Very few languages have this notion, I only know of C++ (but don't get out much).
The key problem that this needs to be enforced by the CLR. C++ doesn't need to enforce this at runtime, only a C++ compiler is required to ensure that const contracts are observed. It has no support at all for language interop, beyond a bolt-on like COM.
This won't fly in .NET, there's little point in declaring a reference immutable and have that verified by the compiler when another language can stomp all over it because it doesn't have the syntax to express immutability. I reckon we'll get it some day, not Real Soon.
As a minor point, you don't have to write (a.b).i = 100; but simply
a.b.i = 100;
Back to your question, I don't think it defeats the purpose. You can still not do the following:
a.b = new B();
because there's no public set(). If you want the member i of class B to be read only, you can do the same thing as you did to member _b of class A by making it private and providing a public get(), but not set(). Off the top my head, doing what you propose might lead to many unexpected consistencies (I'm sure the language designers did not overlook this).
Entirely dependent on the situation, but read only access to a mutable object is a commonly used design. In many cases you simply want to ensure that the object itself remains the same.
Some classes (like String object in Java, and I believe in C# as well) are entirely immutable, where as others are only partially mutable. Consider an ActiveRecord style of object for which most fields are mutable, but the ID is immutable. If your class holds an ActiveRecord in a read only property, external classes cannot swap it for a different ActiveRecord object and thus change the ID, which might break assumptions within your class.
I disagree. Your property is for the class B, not for the members of class B. This means you can't assign a new Object to b. It doesn't mean that B's public members suddenly become private.
readonly applies to the class property, not the object that the property refers to. It keeps you from being able to write a.b = new B();, and that is all it does. It places no constraints on what you can do to the object once you get a reference to it. I think what you are discovering is that readonly make the most sense when applied to value types or immutable class types.
Another use case:
interface INamedPerson
{
String Name { get; }
}
class Bob : INamedPerson
{
public String Name { get; set; }
}
class Office
{
// initialisation code....
public INamedPerson TheBoss { get; }
public IEnumerable<INamedPerson> Minions { get; }
}
Now, if you have an instance of the Office, as long as you don't go cheating with casts, you have read-only access to everyone's names, but can't change any of them.
Ah. Encapsulation does the instantiated class inherit the containing class's access level. Exposing type B as a public property of type A. 'B.i' is public so it should be accessible from outside the same way 'A.b' is public.
A.b returns a reference of a privately accessible type B, however type B has a publicly accessible field i. My understanding is that you can set the i field of B but you can't set the b property of A externally. The B type property of A is readonly however the reference to type B does not define the same readonly access to its fields.
I'm sure you can modify the definition of type B to suit your need for the access level of B's fields or properties.
Related
public class ClassA
{
private SomeOtherClass _someOtherClass = new SomeOtherClass();
}
or
public class ClassB
{
private SomeOtherClass _someOtherClass;
public ClassB()
{
_someOtherClass = new SomeOtherClass();
}
}
or
public ClassC
{
SomeOtherClass _someOtherClass
public SomeOtherClass someOtherClass
{
get{
if(_someOtherClass == null)
{
_someOtherClass = new SomeOtherClass();
}
return _someOtherClass;
}
}
}
All of the above accomplish populating a property with an instance of an object. Is there a benefit to one of them over the other ones? In practice, I only use C when I don't have control over the construction of a class (like in a GUI). A smells a bit to me, but I don't have a concrete reason for that smell.
Note I am omitting the Inversion Of Control (IOC) pattern from the discussion as the benefits of that are well known and I of course use it often. This question is more about the case of a simple class that may not need that pattern.
A and B are almost the same (implementation details on the order, but not important in this case).
I would use C when:
The initialization of the variable can be delayed, or isn't frequently used;
I want to optimize the initialization time and memory of the class.
Another option for C is the use of Lazy<T>, but that is out of scope for the question I think.
A and B are (as said in other answers) basically the same. The property is populated when the class is constructed.
C doesn't populate the property on construction of the class, but only when it's accessed, which can be useful for a number of reasons (for example performance). Furthermore, it also has the side-effect that the property will never be able to be 'null' (whenever it's accessed, which could be an advantage or a disadvantage, depending on what the property is used for.
Well, the first and second example works the same, but I can say that the second one is much cleaner than the first one, because the instantiation is in the constructor, and the purpose of the constructor is usually to initialize the object's members that can be defined at that moment. In this way, you can easily know what has been instantiated just by looking at the constructor, and not searching through all the fields. In any of the first two cases, you could mark the field as readonly if you don't change it's value after that.
I see the third one as a kind of lazy loading, because you will initialize the field when you get the property. I use this when I am not sure if I will use the object within the class, so it is created per request. However, it has the minimal overhead of checking everytime if the field is instantiated, but it's nothing to worry about with current hardware. If you will use the object only within the class, you can mark the property as private, because it has no reason to be seen from the outside.
I know that when using auto-properties, the compiler creates its own backing field behind the screen. However, in many programs I read to learn from, I see people explicitly write
private int _backingField;
public int Property { get { return _backingField; } }
What is the difference between above, and below?
public int Property { get; private set; }
I understand that its obvious to use the property when you actually have side-effects in the getter or setter, but that's often not the case. Also, I understand that you have to explicitly use the backing field in the case of structs, you can't access their members via properties.
The only difference I have been able to find is that the way of calling the value is different inside the class it is defined in. Is it then simple preference, or is there something more to calling a value through its property or by directly accessing the field?
Simple conventions?
There's not much difference between those two snippets - you can't pass a property by reference, for example, but that's rarely an issue. However, if you want the field to be readonly, like this:
private readonly int _backingField;
public int Property { get { return _backingField; } }
then there's a difference. The code I've written above prevents the value from being changed elsewhere within the class, making it clear that this is really meant to be immutable. I'd really like to be able to declare a read-only field with a read-only automatically implement property, settable only within the constructor - but that's not available at the moment.
This is rather confusing, by the way:
Also, I understand that you have to explicitly use the backing field in the case of structs, you can't access their members via properties.
What do you mean? You can definitely use properties within structs. Are you talking about backing fields which are mutable structs, i.e. the difference between:
foo.someField.X = 10;
and
foo.SomeProperty.X = 10;
? If so, I normally avoid that being an issue by making my structs immutable to start with :)
Please explain the following error on struct constructor. If i change struct to class
the erros are gone.
public struct DealImportRequest
{
public DealRequestBase DealReq { get; set; }
public int ImportRetryCounter { get; set; }
public DealImportRequest(DealRequestBase drb)
{
DealReq = drb;
ImportRetryCounter = 0;
}
}
error CS0188: The 'this' object cannot be used before all of its fields are assigned to
error CS0843: Backing field for automatically implemented property
'DealImportRequest.DealReq' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
As the error message recommends, you can resolve this by calling the default constructor from a constructor initializer.
public DealImportRequest(DealRequestBase drb) : this()
{
DealReq = drb;
ImportRetryCounter = 0;
}
From the language specification:
10.7.3 Automatically implemented properties
When a property is
specified as an automatically
implemented property, a hidden backing
field is automatically available for
the property, and the accessors are
implemented to read from and write to
that backing field. [...] Because the
backing field is inaccessible, it can
be read and written only through the
property accessors, even within the
containing type. [...] This
restriction also means that definite
assignment of struct types with
auto-implemented properties can only
be achieved using the standard
constructor of the struct, since
assigning to the property itself
requires the struct to be definitely
assigned. This means that user-defined
constructors must call the default
constructor.
The other (more verbose) alternative, of course, is to manually implement the properties and set the backing fields yourself in the constructor.
Do note that the struct you have there is mutable. This is not recommended. I suggest you either make the type a class (your compilation problems should go away immediately) or make the type immutable. The easiest way to accomplish this, assuming the code you have presented is the entire struct, would be to make the setters private (get; private set;). Of course, you should also make sure that you don't add any mutating methods to the struct afterwards that rely on private access to modify the fields. Alternatively, you could back the properties with readonly backing fields and get rid of the setters altogether.
The code you have is equivalent to the following code:
public struct DealImportRequest
{
private DealRequestBase _dr;
private int _irc;
public DealRequestBase DealReq
{
get { return _dr; }
set { _dr = value; }
}
public int ImportRetryCounter
{
get { return _irc; }
set { _irc = value; }
}
/* Note we aren't allowed to do this explicitly - this is didactic code only and isn't allowed for real*/
public DealImportRequest()
{
this._dr = default(DealRequestBase); // i.e. null or default depending on whether this is reference or value type.
this._irc = default(int); // i.e. 0
}
public DealImportRequest(DealRequestBase drb)
{
this.DealReq = drb;
this.ImportRetryCounter = 0;
}
}
Now, all I have done here is remove the syntactic sugar that:
Implements automatic properties.
Works out which members are dealt with relative to this.
Gives all structs a default no-parameter constructor.
The first two are optional (you could write them explicitly if you wished) but the third is not - we aren't allowed to write our own code for a struct's parameterless constructor, we have to go with one that works like the one in the code above being given to us automatically.
Now, looked at here, suddenly the meaning of the two errors becomes clear - your constructor is implicitly using this before it's fields are assigned (error 188) and those fields are those backing the automatic properties (error 843).
It's a combination of different automatic features that normally we don't have to think about, but in this case don't work well. We can fix this by following the advice in the error message for 843 and calling the default constructor as part of your explicit constructor:
public DealImportRequest(DealRequestBase drb)
:this()
{
DealReq = drb;
ImportRetryCounter = 0;
}
Considering this in relation to my expanded version of your code above, you can see how this solves the problem, because it calls the constructor that assigns to the backing fields before it proceeds.
I would recommend not using auto-properties with structures unless you have a good reason to use them. Wrapping a class field in a read-write property is useful because it makes it possible for an instance to control the circumstances where it may be read or written, and take action when a read or write takes place. Further, code within an object instance can identify the instance being acted upon, and may thus perform a special action only when reading and writing a particular instance. Using an auto-property in an early version of a class will make it possible for future versions of the class to use a manually-implemented property including the aforementioned benefits while retaining compatibility with already-compiled client code. Unfortunately, wrapping a struct field in a read-write property doesn't offer those same benefits because the fields of one struct instance can be copied to another without either instance having any say in the matter. If the semantics of a struct allow a property to be written with arbitrary values in most instances [as would be the case for an auto-property], then any legitimate replacement would be semantically equivalent to a field.
I have a class with various public properties which I allow users to edit through a property grid. For persistence this class is also serialized/deserialized to/from an XML file through DataContractSerializer.
Sometimes I want to user to be able to save (serialize) changes they've made to an instance of the class. Yet at other times I don't want to allow the user to save their changes, and should instead see all the properties in the property grid as read only. I don't want to allow users to make changes that they'll never be able to save later. Similar to how MS Word will allow users to open documents that are currently opened by someone else but only as read only.
My class has a boolean property that determines if the class should be read-only, but is it possible to use this property to somehow dynamically add a read-only attributes to the class properties at run-time? If not what is an alternative solution? Should I wrap my class in a read-only wrapper class?
Immutability is an area where C# still has room to improve. While creating simple immutable types with readonly properties is possible, once you need more sophisticated control over when type are mutable you start running into obstacles.
There are three choices that you have, depending on how strongly you need to "enforce" read-only behavior:
Use a read-only flag in your type (like you're doing) and let the caller be responsible for not attempting to change properties on the type - if a write attempt is made, throw an exception.
Create a read-only interface and have your type implement it. This way you can pass the type via that interface to code that should only perform reads.
Create a wrapper class that aggregates your type and only exposes read operations.
The first option is often the easiest, in that it can require less refactoring of existing code, but offers the least opportunity for the author of a type to inform consumers when an instance is immutable versus when it is not. This option also offers the least support from the compiler in detecting inappropriate use - and relegates error detection to runtime.
The second option is convenient, since implementing an interface is possible without much refactoring effort. Unfortunately, callers can still cast to the underlying type and attempt to write against it. Often, this option is combined with a read-only flag to ensure the immutability is not violated.
The third option is the strongest, as far as enforcement goes, but it can result in duplication of code and is more of a refactoring effort. Often, it's useful to combine option 2 and 3, to make the relationship between the read-only wrapper and the mutable type polymorphic.
Personally, I tend to prefer the third option when writing new code where I expect to need to enforce immutability. I like the fact that it's impossible to "cast-away" the immutable wrapper, and it often allows you to avoid writing messy if-read-only-throw-exception checks into every setter.
If you are creating a library, it is possible to define a public interface with a private/internal class. Any method which needs to return an instance of your read-only class to an external consumer should instead return an instance of the read-only interface instead. Now, down-casting to a concrete type is impossible since the type isn't publicly exposed.
Utility Library
public interface IReadOnlyClass
{
string SomeProperty { get; }
int Foo();
}
public interface IMutableClass
{
string SomeProperty { set; }
void Foo( int arg );
}
Your Library
internal MyReadOnlyClass : IReadOnlyClass, IMutableClass
{
public string SomeProperty { get; set; }
public int Foo()
{
return 4; // chosen by fair dice roll
// guaranteed to be random
}
public void Foo( int arg )
{
this.SomeProperty = arg.ToString();
}
}
public SomeClass
{
private MyThing = new MyReadOnlyClass();
public IReadOnlyClass GetThing
{
get
{
return MyThing as IReadOnlyClass;
}
}
public IMutableClass GetATotallyDifferentThing
{
get
{
return MyThing as IMutableClass
}
}
}
Now, anyone who uses SomeClass will get back what looks like two different objects. Of course, they could use reflection to see the underlying types, which would tell them that this is really the same object with the same type. But the definition of that type is private in an external library. At this point, it is still technically possible to get at the definition, but it requires Heavy Wizardry to pull off.
Depending on your project, you could combine the above libraries into one. There is nothing preventing that; just don't include the above code in whatever DLL you want to restrict the permissions of.
Credit to XKCD for the comments.
Why not something like:
private int someValue;
public int SomeValue
{
get
{
return someValue;
}
set
{
if(ReadOnly)
throw new InvalidOperationException("Object is readonly");
someValue= value;
}
I would use a wrapper class that keeps everything read-only. This is for scalability, reliability and general readability.
I do not foresee any other methods of doing this that will provide the above three mentioned benefits as well as something more. Definitely use a wrapper class here in my opinion.
You can not get compile-time checks (like given with the keyword readonly) by changing a property to readonly at runtime. So there is no other way, as to check manually and throw an exception.
But propably it is better to re-design access to the class. For example create a "writer class", which checks if the underling "data class" can currently be written or not.
You can use PostSharp to create OnFieldAccessAspect that will not pass new value to any field when _readOnly will be set to true. With aspect code repetition is gone and there will be no field forgotten.
Would something like this help:
class Class1
{
private bool _isReadOnly;
private int _property1;
public int Property1
{
get
{
return _property1;
}
set
{
if (_isReadOnly)
throw new Exception("At the moment this is ready only property.");
_property1 = value;
}
}
}
You need to catch exceptions when setting properties.
I hope this is something you are looking for.
I have a class Bar with a private field containing the reference type Foo. I would like to expose Foo in a public property, but I do not want the consumers of the property to be able to alter Foo... It should however be alterable internally by Bar, i.e. I can't make the field readonly.
So what I would like is:
private _Foo;
public Foo
{
get { return readonly _Foo; }
}
...which is of course not valid. I could just return a clone of Foo (assumming that it is IClonable), but this is not obvious to the consumer. Should I change the name of the property to FooCopy?? Should it be a GetCopyOfFoo method instead? What would you consider best practice? Thanks!
It sounds like you're after the equivalent of "const" from C++. This doesn't exist in C#. There's no way of indicating that consumers can't modify the properties of an object, but something else can (assuming the mutating members are public, of course).
You could return a clone of the Foo as suggested, or possibly a view onto the Foo, as ReadOnlyCollection does for collections. Of course if you could make Foo an immutable type, that would make life simpler...
Note that there's a big difference between making the field readonly and making the object itself immutable.
Currently, the type itself could change things in both ways. It could do:
_Foo = new Foo(...);
or
_Foo.SomeProperty = newValue;
If it only needs to be able to do the second, the field could be readonly but you still have the problem of people fetching the property being able to mutate the object. If it only needs to do the first, and actually Foo is either already immutable or could be made immutable, you can just provide a property which only has the "getter" and you'll be fine.
It's very important that you understand the difference between changing the value of the field (to make it refer to a different instance) and changing the contents of the object that the field refers to.
Unfortunately, there's no easy way around this in C# at the moment. You could extract the "read only part" of Foo in an interface and let your property return that instead of Foo.
Making a copy, a ReadOnlyCollection, or having Foo be immutable are usually the three best routes, as you've already speculated.
I sometimes favor methods instead of properties whenever I'm doing anything more significant than simply returning the underlying field, depending on how much work is involved. Methods imply that something is going on and raise more of a flag for consumers when they're using your API.
"Cloning" the Foo objects you receive and give back out is a normal practice called defensive copying. Unless there is some unseen side-effect to cloning that will be visible to the user, there is absolutely no reason to NOT do this. It is often the only way to protect your classes' internal private data, especially in C# or Java, where the C++ idea of const is not available. (IE, it must be done in order to properly create truly immutable objects in these two languages.)
Just to clarify, possible side effects would be things like your user (reasonably) expecting that the original object be returned, or some resource being held by Foo that will not be cloned correctly. (In which case, what is it doing implementing IClonable?!)
If you don't want anyone to mess with your state...don't expose it! As others have said, if something needs to view your internal state, provide an immutable representation of it. Alternatively, get clients to tell you to do something (Google for "tell don't ask"), instead of doing it themselves.
To clarify Jon Skeet's comment you can make a view, that is an immutable wrapper class for the mutable Foo. Here's an example:
class Foo{
public string A{get; set;}
public string B{get; set;}
//...
}
class ReadOnlyFoo{
Foo foo;
public string A { get { return foo.A; }}
public string B { get { return foo.B; }}
}
You can actually reproduce the behaviour of C++ const in C# - you just have to do it manually.
Whatever Foo is, the only way the caller can modify its state is by calling methods on it or setting properties.
For example, Foo is of type FooClass:
class FooClass
{
public void MutateMyStateYouBadBoy() { ... }
public string Message
{
get { ... }
set { ... }
}
}
So in your case, you're happy for them to get the Message property, but not set it, and you're definitely not happy about them calling that method.
So define an interface describing what they're allowed to do:
interface IFooConst
{
public string Message
{
get { ... }
}
}
We've left out the mutating method and only left in the getter on the property.
Then add that interface to the base list of FooClass.
Now in your class with the Foo property, you have a field:
private FooClass _foo;
And a property getter:
public IFooConst Foo
{
get { return _foo; }
}
This basically reproduces by hand precisely what the C++ const keyword would do automatically. In psuedo-C++ terms, a reference of type const Foo & is like an automatically generated type that only includes those members of Foo that were marked as const members. Translating this into some theoretical future version of C#, you'd declare FooClass like this:
class FooClass
{
public void MutateMyStateYouBadBoy() { ... }
public string Message
{
get const { ... }
set { ... }
}
}
Really all I've done is merged the information in IFooConst back into FooClass, by tagging the one safe member with a new const keyword. So in a way, adding a const keyword wouldn't add much to the language besides a formal approach to this pattern.
Then if you had a const reference to a FooClass object:
const FooClass f = GetMeAFooClass();
You would only be able to call the const members on f.
Note that if the FooClass definition is public, the caller could cast an IFooConst into a FooClass. But they can do that in C++ too - it's called "casting away const" and involves a special operator called const_cast<T>(const T &).
There's also the issue of interfaces not being very easy to evolve between versions of your product. If a third party may implement an interface you define (which they are free to do if they can see it), then you can't add new methods to it in future versions without requiring others to recompile their code. But that's only a problem if you are writing an extensible library for others to build on. Maybe a built-in const feature would solve this problem.
I was thinking about similar security things. There is probably a way. Quite clear but not short. The general idea is quite simple. However I always found some ways around so never tested it. But you could check it - maybe it will work for you.
This is pseudo code, but I hope idea behind it is clear
public delegate void OnlyRuller(string s1, string s2);
public delegate void RullerCoronation(OnlyRuller d);
class Foo {
private Foo();
public Foo(RullerCoronation followMyOrders) {
followMyOrders(SetMe);
}
private SetMe(string whatToSet, string whitWhatValue) {
//lot of unclear but private code
}
}
So in class which creates this property you have access to SetMe method, but it's still private so except for creator Foo looks unmutable.
Still for anything bigger than few properties this will probably became soon super mess - that's why I always preferred other ways of encapsulation. However if it's super important for you to not allow the client to change Foo, than this is one alternative.
However, as I said, this is only theory.