Is there a way to have a private readonly field in a class that could be assigned a value anywhere in the class, but only once??
That is, I am looking for a private read
This looks like a good candidate for declaration assignment or singleton.
public class SomeClass {
private readonly Type t = typeof(SomeClass);
}
Or otherwise, like the others said, make an internal or so property with only a setter, then assign a value to it.
public class SomeClass {
private Type t;
internal Type Type {
set {
if (t == null) t = value;
}
}
}
You could create a generic struct to automate the process:
public struct WriteOnce<T>
{
private T? _value;
public T Value
{
get { return _value; }
set
{
if (_value.HasValue) throw new InvalidOperationException();
_value = value;
}
}
}
EDIT I just realized the above won't even compile. The compiler doesn't let _value's type to be Nullable, because the T in Nullable must be a non-nullable type.
Here's an implementation that will work a bit better:
public struct WriteOnce<T>
{
private T _value;
private bool _hasValue;
public bool HasValue { get { return _hasValue; } }
public T Value
{
get { return _value; }
set
{
if (HasValue) throw new InvalidOperationException();
_value = value;
_hasValue = true;
}
}
public static implicit operator T(WriteOnce<T> x)
{
return x.Value;
}
public WriteOnce(T val)
{
_value = val;
_hasValue = true;
}
}
Note I said it would work better - not that it would work well. There are still some gotchas on using it:
First, the compiler will complain if it detects that you're trying to use it without assigning something to it first. Initializing it like so will take care of that:
WriteOnce<int> foo = default(WriteOnce<int>);
Second, even if it throws an exception on modification, C# will still happily let you overwrite it. So while this does encapsulate some of the functionality; you should still wrap it in a property to prevent misuse if it's going to end up exposed in an object's interface.
private WriteOnce<int> _someInt = default(WriteOnce<int>);
public int SomeInt
{
get { return _someInt; }
set { _someInt.Value = value; }
}
However, that still doesn't really get around the last egregious error I committed in the original snippet, which was creating a mutable struct. If you're doing a lot of something like this it might be worth violating that principle for the sake of not repeating yourself, but this is definitely a potential trap that would need to be commented carefully and kept out of any public interfaces.
If it's just a one-off, though, what others have suggested about just directly implementing a property is less complicated and safer.
The short answer is no. The only place you can have a one-time assignment that is compiler checked is in the constructor. You could create a system where you'd get a run-time error if an assignment was attempted more than once but there is no C# construct to do this
There's no language support for that, but you could make a setter, which implemented the desired behavior. Obviously that would not give you compile time errors, but without the language support that is probably the best you can do.
You can use a private property that checks to see if it was assigned to and only assign a value if it hasn't been.
int? _writeOnceField;
private int? WriteOnce
{
set
{
if (!_writeOnceFiled.HasValue)
{
writeOnceFiled = value;
}
else
{
// Throw exception
}
}
}
I think I achieved a way to do it, if it is done in the constructor. It could also be on the variable declaration line. If done outside those contexts, you will receive an error: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
public class BillLine
{
public BillLine(Bill bill)
{
m_Bill = bill;
}
private readonly Bill m_Bill;
public Bill Bill
{
get { return m_Bill; }
//supposed to be set only in the constructor
}
//(...)
}