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.
Related
I've been using ReSharper to do some work on cleaning up a C# codebase. I had been using both private fields in model classes along with public properties. However, I'm finding that I can simply take the properties that have no backing fields and convert them into auto-properties. These are model classes; no methods exist within them to impact the data in the objects. Is it better to just use the auto-properties?
EDIT: Including example of "Backing fields"
public class Gizmo
{
//this is what I call the "backing" field, only because it's "behind" the
//publicly-accessible property and you access it through the property
private Int32 _count;
//and this is the property, of course
public Int32 Count
{
get { return _count; }
set { _count = value; }
}
}
Is it better to just use the auto-properties
If your property involve is simple get;set, you can just use a "auto-property". If I am not wrong, compiler will create a private backing field behind the scenes.
If in your property, you are doing some kind of validation before; say before set then it makes sense to use a property with a backing field (non-auto)
An example would be
private string name;
public string MyName {
get {
return name;
}
set {
name = (value == null)
? "Anonymous" : value;
}
}
Methods are irrelevant here. If you have a property of:
private int foo;
public int Foo
{
get { return foo; }
set { foo = value; }
}
Then it absolutely makes sense to turn that into:
public int Foo { get; set; }
If any other code uses the private field, you can just change it to use the property instead.
This is pretty much a code-style question. So you should have a standard for model properties throughout your project or solution. If you find that the auto properties makes your intent more obvious, by all means use them--just use them consistently.
As in title: what is the difference between:
private readonly string name = "ourName";
and
private string name { get { return "ourName" } }
The first version is part of the state of the object - it's just a field. It can still be changed within the constructor body, too.
The second version is just a property - it's effectively a method which returns the same value every time you call it, and isn't really part of the state of the object. (There's no field involved.)
The first is a field. The second is a property. The field holds the value "ourName" as local state. The property provides a method stateless accessing the literal "ourName".
You can set the field and mutate the state of the field in a constructor. You can also pass the field to a ref or out parameter of a method in the constructor.
None of these statements are true about the property. All you can do with the property is read the value returned by invoking the underlying get_name() method (which always returns the same literal value "ourName". Furthermore, consider these examples to see how the field case can be used in contrast to the property:
public class ExampleWithField
{
public ExampleWithField(){
this.name = "Not our name"; // the value will be "Not our name"
}
private readonly string name = "ourName";
}
public class ExampleWithFieldAndRefParam
{
public ExampleWithFieldAndRefParam(){
SetRefValue(ref this.name); // the value will be "Not our nameourName"
}
static void SetRefValue(ref string value){ value = "Not our name" + value; }
private readonly string name = "ourName";
}
public class ExampleWithFieldAndOutParam
{
public ExampleWithFieldAndOutParam(){
SetOutValue(out this.name); // the value will be "Not our name"
}
static void SetOutValue(out string value){ value = "Not our name"; }
private readonly string name = "ourName";
}
public class ExampleWithProperty
{
public ExampleWithProperty(){
this.name = "Not our name"; // this will not compile.
}
private string name { get { return "ourName"; } }
}
Also if you use reflection or serialization, it will behave different, ie: the GetProperties() method won't return the field in the first case and the field won't be serialized on the last one.
readonly field can be initialized/set in constructor.
property with only get works like function. can not be set in common case
A readonly field could be assigned to by a constructor. A property with no set method couldn't be assigned to by anything.
this is a field declaration that can only be set during declaration:
readonly string name = "abc";
or inside of a the class constructor.
Properties on the other hand are like syntactic sugar for methods. (i.e. get is for getFoo() and set is for setFoo(object value).
so the following line is actually compiled to a single method:
string name { get { return "xyz"; } }
this is why you cannot use properties as values to out or ref parameters
Is anything like this possible? I'm assuming not, but it looks good to me:
class MyClass {
public int Foo {
get { return m_foo; }
set {
// Bounds checking, or other things that prevent the use
// of an auto-implemented property
m_foo = value;
}
// Put the backing field actually *in* the scope of the property
// so that the rest of the class cannot access it.
private int m_foo;
}
void Method() {
m_foo = 42; // Can't touch this!
}
}
Of course I know this syntax is incorrect, and this will not compile. It was hypothetical-future-C# for the sake of clearly portraying my idea. I apologize for the somewhat hypothetical question, but it is too specific for Programmers.SE.
Something like this could be implemented in the compiler that would serve one purpose: Only allow the property's get and set accessors to see the field, essentially allowing the property to be self-contained (as auto-implemented properties are) while allowing additional get/set logic.
The short answer is no, that's not possible in C# today.
We get a feature request like this fairly often; it's a nice feature in its more general form. The more general form is to more clearly make the lifetime of a local variable orthogonal to its scope.
Just to make sure those terms are clear: a variable is a storage location, possibly named. Every variable has a lifetime: the amount of time at runtime in which the variable is guaranteed to refer to valid storage. The scope of a name is the region of text in which that name may be used; it is a compile-time concept, not a runtime concept. A local variable is a variable whose scope is a statement block.
In many languages, the lifetime of a local variable is closely tied to its scope: when control logically enters the scope at runtime, the lifetime begins and when it leaves the scope, the lifetime ends. This is true in C# with some notable caveats:
The lifetime of a local may be extended or truncated if the runtime can determine that doing so has no consequence to the action of managed code on the current thread. The actions of other threads (like the finalizer thread) and unmanaged code on the current thread are implementation-defined.
The lifetime of a local that is in an iterator block, an async method, or a closed-over outer variable of an anonymous function, may be extended to match or exceed the lifetime of the iterator, task, delegate or expression tree that uses it.
Clearly it is not a requirement that the lifetime and scope of a local be tied together in any way. It would be nice if we could explicitly have locals that have the lifetime of an instance or static field, but the scope of a local. C has this feature; you can make a "static" local variable. C# does not. Your proposal is essentially to allow a local variable within the block of the property that has the lifetime of the instance but whose scope is restricted to the block.
I would classify this feature as "nice". We have a list of potential "nice" features literally as long as your arm that we don't have time to implement, so I wouldn't expect this one to make it to the top of the list any time soon. Thanks for the feedback though; it helps us prioritize that list somewhat.
Here's my take on that:
public class WrappedField<T>
{
public class Internals
{
public T Value;
}
private readonly Internals _internals = new Internals();
private readonly Func<Internals, T> _get;
private readonly Action<Internals, T> _set;
public T Value
{
get { return _get(_internals); }
set { _set(_internals, value); }
}
public WrappedField(Func<Internals, T> get, Action<Internals, T> set)
{
_get = get;
_set = set;
}
public WrappedField(Func<Internals, T> get, Action<Internals, T> set, T initialValue)
: this(get, set)
{
_set(_internals, initialValue);
}
}
Usage:
class Program
{
readonly WrappedField<int> _weight = new WrappedField<int>(
i => i.Value, // get
(i, v) => i.Value = v, // set
11); // initialValue
static void Main(string[] args)
{
Program p = new Program();
p._weight.Value = 10;
Console.WriteLine(p._weight.Value);
}
}
According to the C# 4.0 language specifications.
However, unlike fields, properties do not denote storage locations.
Instead, properties have accessors that specify the statements to be
executed when their values are read or written.
Adding a field would require a memory location. So no, this is not possible.
If you would like to avoid generics, you could always hide the _backingField and the bounds checking in a private inner class. You could even hide it further by making the outer class partial. Of course, there would have to be some delegating going on between the outer and the inner class, which is a bummer. Code to explain my thoughts:
public partial class MyClass
{
public int Property
{
get { return _properties.Property; }
set { _properties.Property = value; }
}
public void Stuff()
{
// Can't get to _backingField...
}
}
public partial class MyClass
{
private readonly Properties _properties = new Properties();
private class Properties
{
private int _backingField;
public int Property
{
get { return _backingField; }
set
{
// perform checks
_backingField = value;
}
}
}
}
But this is a lot of code. To justify all that boiler plate, the original problem has to be quite severe...
Nope, the only thing that can be within the the body of the property is the get and set.
Well, it's rather difficult to deal with, probably not very performant, and not something I'd really use, but technically it's a way of obscuring the backing field from the rest of the class.
public class MySuperAwesomeProperty<T>
{
private T backingField;
private Func<T, T> getter;
private Func<T, T> setter;
public MySuperAwesomeProperty(Func<T, T> getter, Func<T, T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value
{
get
{
return getter(backingField);
}
set
{
backingField = setter(value);
}
}
}
public class Foo
{
public MySuperAwesomeProperty<int> Bar { get; private set; }
public Foo()
{
Bar = new MySuperAwesomeProperty<int>(
value => value, value => { doStuff(); return value; });
Bar.Value = 5;
Console.WriteLine(Bar.Value);
}
private void doStuff()
{
throw new NotImplementedException();
}
}
I'm currently implementing a poor-man's version of the RSA Algorithm and I wanted the prime numbers d, e, m, and n to be read-only as they will be automatically generated within ithe constructor body. However, I get two different results when I type:
class RSA
{
public RSA()
{
n = 4;
}
private long n { get; private set; }
}
or
class RSA
{
public RSA()
{
n = 4;
}
private long n { get; }
}
Reading the book Accelarated C#, I got the impression that a private set function can be implemented with auto-implemented properties. Turns out I can do it in the constructor itself too, but only for the first version.
Reading the C# 3.0 standard it says:
A property that has both a get accessor and a set accessor is a read-write property, a property that has only a get accessor is a read-only property, and a property that has only a set accessor is a write-only property.
Yet they don't behave equally.
Simple question: Why can I initialize the value in my constructor when I explicitly declare private set, but not if I do it implicitly? What are the differences here?
In the first case the setter is private. This means that you can set the value of this property everywhere from inside this class not only in the constructor. In the second example there's no setter won't be able to set the value. Using readonly field is probably most correct semantically in your case as it will allow you to set its value either in the constructor or directly when declaring the field (if this field shouldn't be visible from outside of this class):
class RSA
{
public RSA()
{
n = 4;
}
private readonly long n;
}
There's no such thing as an implicit autogenerated private setter. If you omit set;, you cannot assign it a value, which will not compile because it can never be assigned.
Additionally, by making n private you cannot access it from outside that class. If that is your intention, there's no point in using a property at all. You can simply declare it as a field: private readonly long n;
If you really want a property with a readonly value, you could use a Property with the explicit backing field IE:
public class RSA {
private readonly long _n;
public long n {
get { return _n; }
}
public RSA()
{
_n = 4;
}
}
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; }