'private static readonly' and static / non-static constructors
I have three objects:
private static readonly Apple a, c;
private readonly Orange b;
This code is called from my constructor:
public SomeClass()
{
a = new Apple();
b = new Orange(a.getDna());
c = new Apple(b.getDna());
}
This is giving me an error Readonly field cannot be used as an assignment target
. If I remove either the static or readonly modifiers it compiles fine. (Is there a wrong warning here?)
While checking the other answers here on SO I found that I have to use a static constructor like:
static SomeClass()
{
a = new Apple();
c = new Apple(b.getDna());
}
public SomeClass()
{
b = new Orange(a.getDna());
}
But this will cause the static constructor to be called first and throw an error since b will not be initialized.
How do I get around this?
PS I am relatively new to C #
source to share
Let's start by defining what is static
and what is the difference between the members static
and instance
.
A static member is a member that doesn't need an instance to exist: it belongs to the class, not to an object (class instance).
Now the modifier readonly
says that only a value can be assigned to a member in the constructor (or in its declaration, but that doesn't matter here).
There are two types of constructors: static constructors and instance constructors ... the difference is the same difference as above and the modifier of readonly
course applies to each type of constructor: static readonly
would mean "you can only change its value in a static constructor" and instance readonly
means "you can change its value in the instance constructor".
The static constructor is called the first time the type is accessed, so it is always called first.
Now in the examples you just randomly change the members to, static
or don't just try if they compile.
Think about it for a second ... in context static
, you don't have an instance at all, so it just isn't possible to access the instance instances in the constructors static
... besides, by the time a static constructor is called and you can't have any an initialized instance, even externally defined, as it will always be called before you can initialize it.
So this line inside a static constructor doesn't make sense:
c = new Apple(b.getDna());
You are trying to access b
which is a member of an instance, but you are not saying which instance should get the value.
You should really rethink your design and think about why the members will be static or not, rather than just "move things around and try to compile and run".
source to share
The error message is actually correct.
First, static means it belongs to the class. Non-stationary means it is one instance. An instance method can change a static variable, but a static method cannot change an instance variable (which instance would it change?)
Considering readonly means you can only initialize at creation time (e.g. constructor.)
You are getting an error because you are trying to assign a static PERMANENT to a static AFTER creating it in the instance constructor.
source to share
You are trying to assign read-only values to static variables inside an instance constructor. The moment you call the instance constructor, the variables are already assigned a value that is null.
public SomeClass()
{
a = new Apple(); // it is already assigned as null.
b = new Orange(a.getDna()); //there is no value assigned to it yet
c = new Apple(b.getDna()); //it is already assigned as null
}
This is because the static constructor is called before the instance constructor. You can get more information here :
The static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.
But then the problem arises when you try to access an instance variable inside a static constructor. At this point, the instance constructor hasn't been called yet, which means that your variable b
hasn't been initialized yet.
You are facing a very common problem when you are trying to mix instance and static variables. This approach can lead to very strange behavior like the one you are encountering.
I suggest that you don't mix these variables, make them static, or make them all instances, but don't mix them. Otherwise, you may face various problems in the near future.
source to share
Is there an incorrect warning here?
Not. The warning is correct. If a field readonly
, we can assign a value to it in two places: in the declaration or in the constructor. Also, if something is there static
, so is its associated constructor static
. Thus, we can assign fields static
, and readonly
in two places:
- After the announcement or
- in the constructor
static
.
We cannot do this in the instance constructor.
Another question is about the inability of the field to static
depend on the instance.
How do I get around this?
Here's a creative way to get around it :
- In the constructor,
static
assignstatic _b
. - In the instance constructor, assign to the
static _b
instanceb
.
We can even assign _b = null
when we're done with it and still access the value we previously assigned b
.
Here's an example:
public class SomeClass
{
private static readonly Apple a, c;
private static Orange _b;
private readonly Orange b;
static SomeClass()
{
a = new Apple();
_b = new Orange(a.getDna());
c = new Apple(_b.getDna());
}
public SomeClass()
{
b = _b;
_b = null;
}
//
// the rest is just class definitions
//
public class Apple
{
public Apple(object o = null) {}
public object getDna() { return new object(); }
}
public class Orange
{
public Orange(object o = null) { }
public object getDna() { return new object(); }
}
}
This allows you to work around the problem.
source to share