I need a field that can be assigned to from where ever I want, but it should be possible to assign it only once (so subsequent assignments should be ignored). How can I do this?
That would not be a readonly field then. Your only options for initializing real readonly fields are field initializer and constructor.
You could however implement a kind of readonly functionality using properties. Make your field as properties. Implement a "freeze instance" method that flipped a flag stating that no more updates to the readonly parts are allowed. Have your setters check this flag.
Keep in mind that you're giving up a compile time check for a runtime check. The compiler will tell you if you try to assign a value to a readonly field from anywhere but the declaration/constructor. With the code below you'll get an exception (or you could ignore the update - neither of which are optimal IMO).
EDIT: to avoid repeating the check you can encapsulate the readonly feature in a class.
Revised implementation could look something like this:
class ReadOnlyField<T> {
public T Value {
get { return _Value; }
set {
if (Frozen) throw new InvalidOperationException();
_Value = value;
}
}
private T _Value;
private bool Frozen;
public void Freeze() {
Frozen = true;
}
}
class Foo {
public readonly ReadOnlyField<int> FakeReadOnly = new ReadOnlyField<int>();
// forward to allow freeze of multiple fields
public void Freeze() {
FakeReadOnly.Freeze();
}
}
Then your code can do something like
var f = new Foo();
f.FakeReadOnly.Value = 42;
f.Freeze();
f.FakeReadOnly.Value = 1337;
The last statement will throw an exception.
Try the following:
class MyClass{
private int num1;
public int Num1
{
get { return num1; }
}
public MyClass()
{
num1=10;
}
}
Or maybe you mean a field that everyone can read but only the class itself can write to? In that case, use a private field with a public getter and a private setter.
private TYPE field;
public TYPE Field
{
get { return field; }
private set { field = value; }
}
or use an automatic property:
public TYPE Field { get; private set; }
Related
I've seen Marc Gravell's answer from May 8 '09 at 13:29
:
public sealed class WriteOnce<T>
{
private T value;
private bool hasValue;
public override string ToString()
{
return hasValue ? Convert.ToString(value) : "";
}
public T Value
{
get
{
if (!hasValue) throw new InvalidOperationException("Value not set");
return value;
}
set
{
if (hasValue) throw new InvalidOperationException("Value already set");
this.value = value;
this.hasValue = true;
}
}
public T ValueOrDefault { get { return value; } }
public static implicit operator T(WriteOnce<T> value) { return value.Value; }
}
Then use, for example:
readonly WriteOnce<string> name = new WriteOnce<string>();
public WriteOnce<string> Name { get { return name; } }
But i could not understand why would one create readonly WriteOnce<T> if its value is private anyway and it's using a property Value that can only be set once.
Also i couldn't get why would one create a property Name that only enables the get but not the set so:
1.You can't set name's value beacuse it's readonly and
2.You can't set it's value through the property cuz it's only get.
You are confusing quite a few things here.
A readonly field means it can only be assigned inside a constructor or via a field initializer. Now WriteOnce is a reference type, so assigning only means that the value stored in name is a reference to the newly created WriteOnce<string> object.
Nothing stops you from doing whenever you want name.Value = "Hello"; because you are not changing the value of name. name = whatever outside a constructor or a field initializer on the other hand is disallowed becuase you are changing the value of the variable to a new reference, but nothing else.
Name is a readonly property, which has as the backing field name.
A read only propery doesn't let you do Name = new WriteOnce<string>(), but Name.Value = "Hello" is perfectly fine.
Anyhow, nowdays, you'd simply use a readonly autoproperty and let the compiler generate all the plumbing code (backing field):
public WriteOnce<string> Name { get }
readonly means that the object can only be created or changed in the constructor. Making it only private and not readonly would allow any method to create new name field instead. So it's true that you could set the Value only once, but if object is not read only you could completely replace it with the new one.
Creatint readonly WriteOnce means that you can set the name value anytime, not just in the constructor, but once you set the value you can't change it and you can't replace it with the new WriteOnce object.
You could re-write the class as a struct to make it a little simpler and easy to read.
struct WriteOnce<T>
{
public T Value { get; }
public WriteOnce(T input)
{
Value = input;
}
public static implicit operator WriteOnce<T>(T input)
{
return new WriteOnce<T>(input);
}
}
Usage:
WriteOnce<string> name = "test";
You can only change the value on instantiation so you will always know what it will be.
If I want a read-only property, I write it like:
public int MyProperty { get { //Code goes here } }
However, the Microsoft example (and a few other examples I've seen) are written like:
public int MyProperty { get; private set; }
Is there any difference between these two, and should I start writing properties like this?
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.
With private setter you can only assign property value inside of instance when property is without setter you can't set its value anywhere.
If you don't use an explicit member assignment in the property, you'll have to declare a private set at least in order to be able to set a value to this property. Otherwise, you'll get a warning at compile-time saying that your property cannot be assigned.
If you use an explicit member, you'll be able to assign a value to this member directly, without needing to add a private set:
private int member ;
public int MyProperty {
get { return member; }
}
// ...
member = 2;
int anotherVariable = MyProperty; // anotherVariable == 2
public int MyProperty
{
get
{
// Your own logic, like lazy loading
return _myProperty ?? (_myProperty = GetMyProperty());
}
}
A property with only a getter is very useful if you need your own logic behind the access of that property, in particular when you need the property to be lazy loaded.
public int MyProperty { get; private set; }
A property with a private setter is useful if you need the property not te be changed from the outside, but still maintained from within the class.
In both cases, you can have a backing data field for the actual value, but in the former, you'll have to maintain that yourself, and in the latter, it is maintained for you by the generated code.
There is a difference when you access the object with reflection.
public class Foo
{
public string Bar { get; private set; }
}
// .....
internal static void Main()
{
Foo foo = new Foo();
foo.GetType().GetProperty("Bar").SetValue(foo, "private?", null);
Console.WriteLine(foo.Bar);
}
I am writing following code,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ReadOnlyObject
{
class Program
{
private readonly int a = 20;
private readonly int b;
public int propa{get;private set;}
public int propb { get; private set; }
public Program(int tmp)
{
b = tmp;
}
static void Main(string[] args)
{
Program obj1 = new Program(30);
Console.WriteLine(obj1.propa); // Console.WriteLine(obj1.a);
Console.WriteLine(obj1.propb); // Console.WriteLine(obj1.b);
Console.Read();
}
}
}
After executing the above i got o/p as follows,
0
0
And when I change the code by replacing two commented statements printing direct member variables I got output as,
20
30
Why is so?
As far I know about properties they are associated with their definition in order the member variables are declared.
You have confusion about auto property, so:
private readonly int a = 20;
private readonly int b;
public int propa{get {return a; }}
public int propb { get {return b;} private set {b = value;} }
now this will print 20, 30
There are two ways to define properties in C#.
The first, the traditional way;
int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
the second, the auto-property;
public int MyProperty {get;set;}
The first contains a backing variable that you reference in the property accessor. The second implicitly creates a backing variable, because the developers of the language understood that there are a lot of cases where you just need a property!
You can put scope on the auto-property, because you might want to prevent people from setting the value, but internally to the object you should be able to update the value of it.
"As far I know about properties they are associated with their
defination in order the member variables are declated."
Just to clarify all of what you were asking, unless I am reading this statement incorrectly, you're thinking that if you declare variable a and b and the property a and property b that they'll be associated. This is an incorrect assumption.
propa and a are not associated in your example. The compiler is making them auto-implemented properties. http://msdn.microsoft.com/en-us/library/bb384054.aspx If you want propa associated with a then you'd do:
public int propa{get { return a;} }
You're not initializing either property. You also can't set the value of b from a setter if it's marked readonly. You can implement your own 'readonly' type by just not letting the value get set more than once. (Although it doesn't stay true to the constraint that it needs to be initialized in the constructor)
Try this:
private readonly int a = 20;
public int A { get { return a; } }
private int b;
private bool bInitialized = false;
public int B
{
get { return b; }
private set
{
if (bInitialized) return;
bInitialized = true;
b = value;
}
}
The way your code is written propb and propa CANNOT be set outside the scope of the class. so remove the keyword private from the set keyword
if you wrote this.propb = b in your constructor, then I think it should work more like you are expecting.
Can somebody help me understand the get & set?
Why are they needed? I can just make a public variable.
Warning: I am assuming you already know about object-oriented programming.
What are properties?
Properties are language elements that allow you to avoid the repetitive getXYZ() accessors and setXYZ() mutators techniques found in other languages, like Java.
Why do they exist?
They aim to solve the following problems:
Saying get and set in the beginning of every access or mutation of a value is annoying and distracting.
In Java, you often say:
class person
{
private int _age;
public void setAge(int value) { /*check value first, then set _age*/ }
public int getAge() { return this._age; }
}
and then consistently say:
if (person.getAge() > blah || person.getAge() < 10)
{
person.setAge(5);
}
After a while, the get and set become rather annoying.
Providing direct access to the actual variable breaks encapsulation, so that's not an option.
How are they used?
They are used just like variables. You read/write to them just like variables.
How are they created?
They are created as methods. You define a pair of methods that:
Return the current value of the property. Oftentimes, this is nothing more than something like the following:
class Person
{
private int _age; //Declare the backing field
public int Age
{
get { return this._age; }
set { ... }
}
}
Set the value of the property:
class Person
{
public int Age
{
get { ... }
set
{
if (value < 0) //'value' is what the user provided
{ throw new ArgumentOutOfRangeException(); } //Check validity
this._age = value;
}
}
}
Other notes:
Auto-implemented Properties
C# 3.0 introduced auto-implemented properties:
public int Age { get; set; }
This is equivalent to:
private int _age; //The name is auto-generated
public int Age { get { return this._age; } set { this._age = value; } }
Why does it exist?
It helps you avoiding breaking changes in client executables.
Let's say you're lazy and don't want to type the whole thing, and decide to expose a variable publicly. You then create an executable that reads from or writes to that field. Then you change your mind and decide that you in fact needed a property, so you change it to one.
What happens?
The depending executable breaks, because the code is no longer valid.
Auto-implemented properties help you avoid that, without extra redundancy in your initial code.
Indexers
Indexers extend the property syntax to let you index objects (surprise!), just like arrays.
For C++ users: This is similar to overloading operator [].
Example:
private int[] _elements;
public int this[int index] //Indexed property
{
get { return this._elements[index]; }
set
{
//Do any checks on the index and value
this._elements[index] = value;
}
}
You then use them like obj[5] = 10;, which is equivalent to calling the set method of obj's indexer.
In fact, System.Collections.Generic.List<T> is indexed:
var list = new List<int>();
list.Add(10);
list[0] = 5; //You're indexing list, as though it were an array!
Isn't that neat? :)
Anything else?
There are many more features to properties, not all of which are available in C#:
Parametrized properties, of which indexers are a special kind
Getter/setter access modifiers (in C#)
Multiple getters or setters (not in C#)
Et cetera
They are called Accessors
The accessor of a property contains the executable statements associated with getting (reading or computing) or setting (writing) the property. The accessor declarations can contain a get accessor, a set accessor, or both.
The body of the get accessor resembles that of a method. It must return a value of the property type.
http://msdn.microsoft.com/en-us/library/w86s7x04.aspx
private string m_Name; // the name field
public string Name // the Name property
{
get
{
return m_Name;
}
}
The set accessor resembles a method whose return type is void. It uses an implicit parameter called value, whose type is the type of the property.
private m_Name;
public string Name {
get {
return m_Name;
}
set {
m_Name = value;
}
}
Then in the incarnation of C# 3, you can do this much easier through auto-properties
public string Name {get; set; } // read and write
public string Name {get; } // read only
public string Name { get; private set; } //read and parent write
http://msdn.microsoft.com/en-us/library/bb384054.aspx
Properties act as accessors to the internal state of an object, hiding the implementation of that state.
So, for example, you may have a first name property in a class
public class Example
{
private string firstName;
public string FirstName
{
get {return this.firstName;}
}
}
So anyone using the class doesn't need to know how first name is stored, they just know they can get a string representation of it. By adding a set you also add a mutator, something which changes an objects internal state
public class Example
{
private string firstName;
public string FirstName
{
get {return this.firstName;}
set {set this.firstName = value;}
}
}
Again you're still isolating how the first name is stored internally (encapsulation), but users can change it by passing in a string.
Simply put, get and set accessors are the functions called on a Property; that is, when you retrieve the value or when you set it. It forces a type of behavior on the way values are retrieved or set.
For example, you may want to have a mechanism to get/set passwords. Generally speaking, you'll only want to compare the hash of a password instead of storing things plaintext, so you'd have the getter variable retrieve the stored hash, and the setter would take the provided input and hash it for storage.
Here's what I mean:
public class User {
//Usery properties here, and...
private string _password;
public string Password {
get {
return _password;
}
set {
_password = SomeHashingFunction(value);
}
}
}
value is the variable provided to the setter from what has been given in the variable assignment. e.g.: someuser.Password = "blah";
Get and set are used in properties. They can each be public, protected, or private. Similar to accessor and mutator methods, they allow some computation when code tries to access/mutate the property. Of course, as long as you define one of get/set, the other is optional.
Example without properties:
private int test;
public int getTest() {
// some computation on test here, maybe?
return test;
}
private void setTest(int test) {
// some error/range checking, maybe?
this.test = test;
}
With properties:
private int test;
public int Test {
get {
// some computation on test here, maybe?
return test;
}
private set {
// some error/range checking, maybe?
test = value; // value is a keyword here
}
}
get{} and set{} are accessors that offer up the ability to easily read and write to private fields. Working with a simple example:
public class Foo()
{
//Field
private int _bar;
//Property
public int Bar
{
get { return _bar; }
set { _bar = value; }
//value is an implicit parameter to the set acccessor.
//When you perform an assignment to the property, the value you
//assign is the value in "value"
}
}
In this case, Bar is a public property that has a getter and a setter that allows access to the private field _bar that would otherwise be inaccessible beyond class Foo.
Now in a class that has an instace of Foo, you can do this:
public class IHasAFoo()
{
private Foo _myFoo = new Foo();
public void SomeMethod()
{
_myFoo.Bar = 42;
}
}
So the public accessor allows you to set the value of the private field back in Foo.
Hope that helps!
In the following code:
public class MovieRepository : IMovieRepository
{
private readonly IHtmlDownloader _downloader;
public MovieRepository(IHtmlDownloader downloader)
{
_downloader = downloader;
}
public Movie FindMovieById(string id)
{
var idUri = ...build URI...;
var html = _downloader.DownloadHtml(idUri);
return ...parse ID HTML...;
}
public Movie FindMovieByTitle(string title)
{
var titleUri = ...build URI...;
var html = _downloader.DownloadHtml(titleUri);
return ...parse title HTML...;
}
}
I asked for something to review my code, and someone suggested this approach. My question is why is the IHtmlDownloader variable readonly?
If it's private and readonly, the benefit is that you can't inadvertently change it from another part of that class after it is initialized. The readonly modifier ensures the field can only be given a value during its initialization or in its class constructor.
If something functionally should not change after initialization, it's always good practice to use available language constructs to enforce that.
On a related note, C# 9 introduces the init accessor method for properties, which indicates the property value can only be set during object construction, e.g.:
class InitExample
{
private double _seconds;
public double Seconds
{
get { return _seconds; }
init { _seconds = value; }
}
}
This ensures that the value of _downloader will not be changed after the constructor was executed. Fields marked as readonly can only be assigned a value from within the constructor(s) of a class.
A readonly field is useful for modelling data that should not change after it has been initialized. You can assign a value to a readonly field by using a initializer when you declare it or in a constructor, but thereafter you cannot change it.