Consider the code below. Fields i and j are initialized before m and n. We know that the parent object is created before the child object, but in my program the compiler is allocating and initializing memory for the child class' member variables before the base class'. Why is that?
class X
{
private int m = 0;
private int n = 90;
public X() { }
}
class Y:X
{
private int i = 8;
private int j = 6;
public Y()
{ }
public static void Main(string []args)
{
Y y1 = new Y();
}
}
This is explained in Eric Lippert's blog:
[...] an initialized readonly field is always observed in its initialized state, and we cannot make that guarantee unless we run all the initializers first, and then all of the constructor bodies.
Not sure why readonly is mentioned here, but for example, this ensures that the following scenarios, albeit being stupid, work:
1.
class Base
{
public Base()
{
if (this is Derived) (this as Derived).Go();
}
}
class Derived : Base
{
X x = new X();
public void Go()
{
x.DoSomething(); // !
}
}
2.
class Base
{
public Base()
{
Go();
}
public virtual Go() {}
}
class Derived : Base
{
X x = new X();
public override void Go()
{
x.DoSomething(); // !
}
}
This order is explicitly stated in C# Language Specification (17.10.2):
[...] constructor implicitly performs the initializations specified by the variable-initializers of the instance fields declared in its class. This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor and before the implicit invocation of the direct base class constructor.
This is one of those rare places where an understanding of procedural methodology makes object-oriented methodology easier to understand. Even though you're working OOP, the compiler still adheres to procedural logic - working start to finish.
A simple example is when the compiler hits private int n = 90. First it allocates space for an integer value, then an identifier to access it as an integer, then assigns it the value of 90. It can't assign the value until it both has the space to stick it AND knows how to access it, nor can it access non-existent space.
In this instance, your derived class Y is built atop the base class X, similar to how the variable n is built atop the "class" integer in the example above. This is triggered by the declaration class Y:X - the compiler can't even start building Y until it understands how to build X.
Child construction code must be allowed to call functions on the parent, which can't work unless the parent is already fully-constructed.
However, the objects share the same memory block. So all the memory is allocated in one go, then the classes are initialized working up the class hierarchy.
Related
According to this link, Constructors enable the programmer to set default values, limit instantiation, and write code that is flexible and easy to read.
class Program
{
static void Main(string[] args)
{
var a = new MyClass();
Console.WriteLine($"i: {a.i}, b: {a.b}"); //result --> i: 0, b: False
}
}
public class MyClass
{
public int i;
public bool b;
public MyClass() { }
}
My constructor doesn't have a single line of code. At what point the members of my class get initialized? And what if I don't provide a default constructor but rather a constructor that take some parameters? The documentation doesn't explain that assertion. Do codes similar to this get injected?
public class MyClass
{
public int i;
public bool b;
public MyClass()
{
i = default;
b = default;
}
}
Thanks for helping
ECMA-334 specification, which defines the C# standard, says this:
10.4.2 - Initially assigned variables
The following categories of variables are classified as initially assigned:
Static variables.
Instance variables of class instances.
Instance variables of initially assigned struct variables.
Array elements.
Value parameters.
Reference parameters.
Variables declared in a catch clause or a foreach statement.
So the compiler ensures that these variables are always set to default. This is easily backed up by the CLR, which always initializes all such variable locations (note that local variables are specifically not in the above list).
ECMA-335, which defines the CLR, says:
I.8.11.2 - Field definitions
snip
Fields not marked as static define the representation of a value of a type by defining the substructure of the value (see §I.8.4.1). Locations for such fields are created within every value of the type whenever a new value is constructed. They are initialized during construction of the new value.
When you define a class it is present virtually like blueprint of any design. So When you move to its implementation it becomes reality. Same goes for object and classes in any Object oriented language. When you define class, you basically define blueprint it does not exist yet but when you create object of class, it is created in memory. So in your first case where you have constructor without any arguments when you create object memory space is reserved based on its member and types.
public class MyClass
{
public int i;
public bool b;
public MyClass() { }
}
In this case when you create object, memory is reserved for int and bool. it does not matter whether you have parameterized constructor where you are assigning values to class members or not. Memory space is reserved with default values for int and bool in heap.
This question already has answers here:
Cannot use 'this' in member initializer?
(3 answers)
Closed 7 years ago.
Why does the compiler give an error about this being unavailable that when initializing an instance variable when defining it?
Keyword 'this' is not available in the current context
The constructor initialization is fine. I understand the scenario here - I just wanted to find the reason (via MSDN or otherwise) why "this" is available to a constructor but not directly if initializing the member variable.
Here is a simple abstraction of the error I'm seeing.
public class ClassA
{
// Gets compiler error that "this" unavailable
protected ClassB _a1 = new ClassB(this);
// Works fine
protected ClassB _a2;
public ClassA() { _a2 = new ClassB(this); }
}
public class ClassB
{
public ClassA A { get; private set; }
public ClassB(ClassA a) { this.A = a; }
}
I was hoping to keep my initialization next to the assignment since the above example is an abstraction of my code where I am defining Lazy valueFactory delegates for 10-15 member variables in which the delegates need the data context passed as a parameter to the constructor. With 15 member variables, I'd prefer to keep the assignment next to the definition on a single line instead of having 15 lines of definitions and then another 15 lines in the constructor initializing each one.
This is basically what I had to do in my actual code:
public class MyContext
{
public ProgramService Programs { get { return _programs.Value; } }
protected Lazy<ProgramService> _programs;
public MyContext()
{
_programs = new Lazy<ProgramService>(() => new ProgramService(this));
}
}
Basically to keep you from relying on the order (textual) and possibly non-usable state of the class under construction. I think the overriding principle at stake is that if it's "complicated" logic, then you should be using a constructor.
Eg., doing this:
class A {
private int x = 1;
private int y = this.x + 1;
}
would lead to different results than:
class A {
private int y = this.x + 1;
private int x = 1;
}
which is a little unexpected. To side-step the issue, but still allow the convenience of inline init - disallowing this makes the ordering not matter.
In your actual code, you could possibly do a lazy check to keep things located together:
public ProgramService Programs {
get {
if (_programs == null) _programs = new ProgramService(this);
return _programs.Value;
}
}
// change this to private to keep subclasses from accessing a possibly null reference
private Lazy<ProgramService> _programs;
Consider the int a variables in these classes:
class Foo {
public int a = 3;
public void addFive() { a += 5; System.out.print("f "); }
}
class Bar extends Foo {
public int a = 8;
public void addFive() { this.a += 5; System.out.print("b " ); }
}
public class test {
public static void main(String [] args){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
I understand that the method addFive() have been overridden in the child class, and in class test when the base class reference referring to child class is used to call the overridden method, the child class version of addFive is called.
But what about the public instance variable a? What happens when both base class and derived class have the same variable?
The output of the above program is
b 3
How does this happen?
There are actually two distinct public instance variables called a.
A Foo object has a Foo.a variable.
A Bar object has both Foo.a and Bar.a variables.
When you run this:
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
the addFive method is updating the Bar.a variable, and then reading the Foo.a variable. To read the Bar.a variable, you would need to do this:
System.out.println(((Bar) f).a);
The technical term for what is happening here is "hiding". Refer to the JLS section 8.3, and section 8.3.3.2 for an example.
Note that hiding also applies to static methods with the same signature.
However instance methods with the same signature are "overridden" not "hidden", and you cannot access the version of a method that is overridden from the outside. (Within the class that overrides a method, the overridden method can be called using super. However, that's the only situation where this is allowed. The reason that accessing overridden methods is generally forbidden is that it would break data abstraction.)
The recommended way to avoid the confusion of (accidental) hiding is to declare your instance variables as private and access them via getter and setter methods. There are lots of other good reasons for using getters and setters too.
It should also be noted that: 1) Exposing public variables (like a) is generally a bad idea, because it leads to weak abstraction, unwanted coupling, and other problems. 2) Intentionally declaring a 2nd public a variable in the child class is a truly awful idea.
From JLS
8.3.3.2 Example: Hiding of Instance Variables This example is similar to
that in the previous section, but uses
instance variables rather than static
variables. The code:
class Point {
int x = 2;
}
class Test extends Point {
double x = 4.7;
void printBoth() {
System.out.println(x + " " + super.x);
}
public static void main(String[] args) {
Test sample = new Test();
sample.printBoth();
System.out.println(sample.x + " " +
((Point)sample).x);
}
}
produces the output:
4.7 2
4.7 2
because the declaration of x in class
Test hides the definition of x in
class Point, so class Test does not
inherit the field x from its
superclass Point. It must be noted,
however, that while the field x of
class Point is not inherited by class
Test, it is nevertheless implemented
by instances of class Test. In other
words, every instance of class Test
contains two fields, one of type int
and one of type double. Both fields
bear the name x, but within the
declaration of class Test, the simple
name x always refers to the field
declared within class Test. Code in
instance methods of class Test may
refer to the instance variable x of
class Point as super.x.
Code that uses a field access
expression to access field x will
access the field named x in the class
indicated by the type of reference
expression. Thus, the expression
sample.x accesses a double value, the
instance variable declared in class
Test, because the type of the variable
sample is Test, but the expression
((Point)sample).x accesses an int
value, the instance variable declared
in class Point, because of the cast to
type Point.
In inheritance, a Base class object can refer to an instance of Derived class.
So this is how Foo f = new Bar(); works okay.
Now when f.addFive(); statement gets invoked it actually calls the 'addFive() method of the Derived class instance using the reference variable of the Base class. So ultimately the method of 'Bar' class gets invoked. But as you see the addFive() method of 'Bar' class just prints 'b ' and not the value of 'a'.
The next statement i.e. System.out.println(f.a) is the one that actually prints the value of a which ultimately gets appended to the previous output and so you see the final output as 'b 3'. Here the value of a used is that of 'Foo' class.
Hope this trick execution & coding is clear and you understood how you got the output as 'b 3'.
Here F is of type Foo and f variable is holding Bar object but java runtime gets the f.a from the class Foo.This is because in Java variable names are resolved using the reference type and not the object which it is referring.
I am new to C# programming.
Please help me.
I created a class Tester:
class Tester
{
public int a = 5;
public int b = a;
}
Question 1 : Why am I not able to use this variable a for initializing the variable b.
Question 2: If I changed the variables to static then it works fine. Why is there a difference?
class Tester
{
public static int a = 5;
public static int b = a;
}
Question 3 : In previous example if I swap the sequence of variable then it works fine why because a is declaring after b . How can it initialize a?
class Tester
{
public static int b = a; // 0
public static int a = 5; // 5
}
There are some icky initialization order issues when you use fields initializers. A simple example would be:
class Test {
int a = b;
int b;
public Test() {
b = 1;
}
}
What will be the value of a? If you use the constructor-initializes-object rule then a will be 1. That however not the way it works under the hood, a would be 0 if the syntax where valid. A side-effect of the way field initializers are implemented, their code is injected into the constructor before the code in the body of the constructor. This problem gets a lot more convoluted when the class inherits base classes that have constructors.
This is too ugly, the C# language designers solved this by simply forbidding this kind of code. The rule is that you cannot reference this in a field initializer, that will create a reference to an object whose class constructor hasn't finished executing.
The rule is relaxed for static fields, there is no this reference and the CLR provides decent guarantees for class initializer execution order. That however doesn't avoid ambiguity, it is an exercise to guess what the field values will be in this example:
class Test {
static int a = b + 1;
static int b = a + 1;
}
Try it and see if you can make sense of the result. It is otherwise well-defined.
Answer1: You cannot use an instance variable to initialize another instance variable. Why? Because the compiler can rearrange these - there is no guarantee that variable "a" will be initialized before "b", so the above line might throw a NullReferenceException.
Answer2: It works fine with static because static are initialize before other variables and their references are not changed.
Please let me know if it helps.
As Anirudh said. You cannot use an instance variable to initialize another instance variable. Why? Because the compiler can rearrange these - there is no guarantee that a will be initialized before b.
You can use constructor for this.
class Tester
{
public int a=5;
public int b;
public Tester()//constructor
{
b=a;
}
}
or
class Tester
{
public static int a = 5;
public static int b;
public Tester()//constructor
{
b = a;
}
}
I'll try to keep this simple.
class MyClass {
private int x = 3;
}
vs.
class MyClass {
private int x;
public MyClass() {
x = 3;
}
}
What's the difference between the two and how do these differences come into play?
Thanks in advance.
class MyClass {
private int x = 3;
}
is same as
class MyClass {
private int x;
MyClass() { // default constructor based on the class access modifier
x = 3;
}
}
These are both the same
But if x were a static variable, they would be different.
Nothing at all. Variable's are set when a constructor is called, you can see this by adding the line MyClass temp = new MyClass() and stepping into it with the debugger, the debugger will go to the line private int x = 3; first.
Initialization of fields are done before constructor is called. But for your example they are same
In your example you actually have instance variable, not the class variable.
Difference comes in the moment when you add new constructor MyClass(Object argument) and forget to set x directly and forget to call original no-arg constructor as well. Making it final, if applicable, will of course force you to remember to set value somewhere.
In the case of class variable things get much more interesting, just change x to static and add following main method to the MyClass and observe results.
public static void main(String ... args) {
MyClass y = null;
System.out.println(y.x);
System.out.println(MyClass.x);
new MyClass();
System.out.println(MyClass.x);
}
As others has mentioned they both are equivalent. The main difference is the readability, duplicity and maintainability of the code. If we expand the given example to have more than one constructor you'll start to notice differences. If the value of x is not to depend on the constructor I'd recommend to initialize the field variable else set the value in the constructors. This will somewhat increase the readability and maintainability of the code and remove duplicated code (in the case were several constructors are to initiate the variable with the same value).