Field initializer accessing `this`: invalid in C#, valid in Java? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
First, an introduction:
This code:
class C
{
int i = 5;
byte[] s = new byte[i];
}
fails to compile with the following error:
A field initializer cannot reference the nonstatic field, method, or property `C.i'
Resharper says something similar: Cannot access non-static field i in static context.
This is inline with what the C# spec says -- that a field initializer can't access the instance currently being created (this) or, by extension, any of the instance fields:
A variable initializer for an instance field cannot reference the
instance being created. Thus, it is a compile-time error to reference
this in a variable initializer, as it is a compile-time error for a
variable initializer to reference any instance member through a
simple-name.
However, this works just fine in Java:
class C {
int i = 5;
byte s[] = new byte[i]; //no errors here
}
Still with me? Ok, here's the question. Err, questions.
In a hypothetical world where this would be valid in C#, I'm wondering: would it even be possible? If so, what would be the pros and cons that it would add to the table?
Also, since it's really supported by Java, do the same pros/cons hold for Java? Or is there a fundamental difference in the way type initializers work in the two languages?

In short, the ability to access the receiver before the constructor body runs is a feature of marginal benefits that makes it easier to write buggy programs. The C# language designers therefore disabled it entirely. If you need to use the receiver then put that logic in the constructor body.
as for why the feature is legal in Java, you'll have to ask a Java designer.

In C#, field initializers are merely convenience semantics for the developer. The compiler moves all field initializers into the body of the constructor ABOVE where the call is made to the base constructor. So fields are initialized going up the ancestor chain, and the class is initialized from the base down.
Static references are ok because they are initialized before anything else.

By no means is this an authoritative answer, but let me make an educated guess.
There is a fundamental difference, and I think the answers to the other questions are related to this difference.
It lies in order-of-type-initialization, especially in the context of inheritance.
So, how does instance initialization work?
In C#:
all instance field initializers run first, "up" the inheritance chain, from most derived to base class.
then the ctors run, "down" the chain, from base to derived.
The possibility of ctors calling each-other or (explicitely) calling ctors of base classes doesn't change the situation, so I'll leave it out.
What basically happens is, this runs for each chass in the chain, starting with the most derived:
Derived.initialize(){
derivedInstance.field1 = field1Initializer();
[...]
Base.Initialize();
Derived.Ctor();
}
A simple example shows this:
void Main()
{
new C();
}
class C: B {
public int c = GetInt("C.c");
public C(){
WriteLine("C.ctor");
}
}
class B {
public int b = GetInt("B.b");
public static int GetInt(string _var){
WriteLine(_var);
return 6;
}
public B(){
WriteLine("B.ctor");
}
public static void WriteLine(string s){
Console.WriteLine(s);
}
}
Output:
C.c
B.b
B.ctor
C.ctor
That means that if accessing fields in a field initializer was valid, I could do this disaster:
class C: B {
int c = b; //b is a field inherited from the base class, and NOT YET INITIALIZED!
[...]
}
In Java:
Long, interesting article about type initialization here. To summarize:
It's a bit more complicated, because besides the notion of instance field initializers, there's the notion of an (optional) instance initializer, but here's the gist of it:
Everything runs down the inheritance chain.
the instance initializer of the base class runs
the field initializers of the base class run
the ctor(s) of the base class run
repeat above steps for the next class down the inheritance chain.
repeat previous step until reaching the most derived class.
Here's the proof: (or run it yourself online)
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
new C();
}
}
class C extends B {
{
WriteLine("init C");
}
int c = GetInt("C.c");
public C(){
WriteLine("C.ctor");
}
}
class B {
{
WriteLine("init B");
}
int b = GetInt("B.b");
public static int GetInt(String _var){
WriteLine(_var);
return 6;
}
public B(){
WriteLine("B.ctor");
}
public static void WriteLine(String s){
System.out.println(s);
}
}
Output:
init B
B.b
B.ctor
init C
C.c
C.ctor
What this means is, by the time a field initializer runs, all inherited fields are already initialized (by initializer OR ctor in base class), so it's safe enough to allow this behaviour:
class C: B {
int c = b; //b is inherited from the base class, and it's already initialized!
[...]
}
In Java, like in C#, the field initializers are run in the order of declaration.
The Java compiler even goes through the effort of checking that the field initializers aren't called out-of-order* :
class C {
int a = b; //compiler error: illegal forward reference
int b = 5;
}
* As an aside, you can access fields out-of-order if the initializer calls an instance method to do so:
class C {
public int a = useB(); //after initializer completes, a == 0
int b = 5;
int useB(){
return b; //use b regardless if it was initialized or not.
}
}

It is because field initialisers are moved into the constructor by the compiler (unless static) and so you would need be explicit in your constructor like this:
class C
{
int i = 5;
byte[] s;
public C()
{
s = new byte[i];
}
}

This is a bit of a non-answer, but I like to think of anything in the body of a class as being sequence-independent. It's not supposed to be sequential code that needs to be evaluated in a particular manner--it's just default state for the class. If you use code like that, you're expecting i to be evaluated before s.
Anyways, you can just make i a const (as it should be), anyways.

Related

static field initialization explanation and its requirement

After looking at so many complicated questions related to this i want to ask the explanation for following code having static field initialization. one more thing i want to know is the requirement of static field initialization. In which scenarios it ll be helpful??
using System;
class Test
{
static void Main()
{
Console.WriteLine("{0} {1}", B.Y, A.X);
}
public static int F(string s)
{
Console.WriteLine(s);
return 1;
}
}
class A
{
static A()
{ }
public static int X = Test.F("Init A");
}
class B
{
static B()
{ }
public static int Y = Test.F("Init B");
}
Output:
Init B
Init A
1 1
When no static constructor is present then output may vary. I am not able to understand the rationale behind it.What difference static field initialization has brought to this fragment?. Can someone please help. I am a newb with c#.
When a type has a static constructor, the runtime is constrained to execute all type initialization immediately before the first use of any member of the type.
When it doesn't have a static constructor, the runtime has much more freedom - it has to execute the type initializer at some point before the first use of a static field or before an instance is constructed, but that's all. You can even observe static methods which don't touch static fields being executed without the type initializer executing.
In your case, both A and B have static constructors, and the order of access to the members is B first, then A, hence your output. Without those static constructors, you'd still be guaranteed to get "1 1" as the last line, and you'd still get both "Init A" and "Init B", but the ordering of them wouldn't be guaranteed.
This is just the way the language and runtime are specified - and usually it has no impact, as usually type initializers should just be setting up the type, with no other side effects. Type initializers should do as little as possible, ideally - if they fail for some reason, the type will never be usable; type initializers aren't retried.
For more details, see my beforefieldinit article and .NET 4.0 type initializer changes blog post.

What's the meaning of making a method static? -For dummies [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have a method that takes a string argument (a file path), and i wanna make it acessible to all forms.
I know that when i use
public static methodname(string path) { //code }
it will work on all forms as long as i call it, and when i dont have static there i have to instantiate it.. the thing is.. why this difference? What does it really means to instantiate? I've read a few topics about it, but i couldn't quite understand how, can you take the time to explain it to a amateur beginner?
This tells the compiler that he method is entirely self-contained, and does not rely on or utilize any object state, or instance-based properties or fields of the class it is defined in. As a consequence, you do not need to instantiate an instance of the type (class or struct) in order to use this method. It becomes like a global function or subroutine which you can call simply by name, (you must use the class/struct name and method name) without any preparation.
to call non-static method MyMethod() on class foo
var f = new foo();
f.MyMethod();
to call static method MyMethod() on class foo
foo.MyMethod();
You can define static methods in a non-static class, (if the method does not rely on any object state doesn't mean the object does not have any state...). but you cannot put non-static methods in a static class (if the method requires access to object state, then it obviously can't be in a class that has no state).
Now you can write a method that does not require object state, and neglect to declare it as static. Then it would require the same usage syntax like a non-static method even though it is functionally static. That is an error the compiler will accept (although many tools like Resharper will warn you about this).
You use non-static classes or object oriented classes, if you want to maintain a state.
When you use static classes, there isn't any state.
For example:
class HelloWorld
{
public string Name {get;set;}
public void SayHello()
{
Console.WriteLine(Name + " hello!");
}
public void SayHi()
{
Console.WriteLine(Name + " hi!");
}
}
You would use the above like this:
HellowWorld obj = new HelloWorld();
obj.Name = "John";
obj.SayHi();
obj.SayHello();
If that was a static class:
static class HelloWorld
{
public static void SayHello(string Name)
{
Console.WriteLine(Name + " hello!");
}
public static void SayHi(string Name)
{
Console.WriteLine(Name + " hi!");
}
}
You would call the above like this:
HelloWorld.SayHello("John");
HelloWorld.SayHi("John");
As you can see, you are repeating yourself.
So it all depends on how you want the class to behave. If you want do and forget, then static class is your friend. If you don't want it to forget something, then use Objects
This is classic programming. Static methods are used when all the data you need is from the parameter. Also static methods are called upon a class. When you make a method static then it uses instance variables to do something. Instantiontain allows a user to initialize all fields in that class then the user can call a method upon that object that behind the scenes uses instance variables to do something.
As you said, a non-static method means that it belows to an object (so you have to instantiate one in order to use the method. On the other hand, a static method below to the class, so when you call it, it has nothing to do with an object.
For example:
class C{
static int f(int i){return i+1;}
}
C.f(2); // returns 3
You only can do it if the method is static, it is, it belongs to a class, not an object. If f() were not be static, you have to instantiate one object to use it:
class C{
int f(int i){return i+1;}
}
C.f(2); // invalid!
C c = new c(); c.f(2); // returns 3
On the other hand, this code is invalid:
class C{
int a;
static int f(){return a;}
}
C.f(); // Invalid: each instance of C has it own attribute a.

What if I don't heed the warning "hides inherited member. To make the current member override that implementation...."

This is maybe a fine point, but it concerns the warning that the compiler issues if you do something like:
class A
{
public virtual void F() { }
}
class B : A
{
public void F() { }
}
Then you get the warning:
'EomApp1.B.F()' hides inherited member 'EomApp1.A.F()'.
To make the current member override that implementation, add the override keyword. Otherwise use the new keyword.
QUESTION: What is the warning actually warning me will happen if I do nothing about it? Will my program function differently if I add the 'new' keyword vs. if I do not?
(Note: I know I could test this easily enough but I figured it was worth asking here)
It will not do anything but the method you have there F() is also not polymorphic. It becomes very easy to make mistake in code if you started to use base class reference hence you are warned. Of course it can be what you want, hence the new keyword just make it more explicit
E.g.
B b1 = new B();
b1.F(); // will call B.F()
A b2 = new B();
b2.F(); // will call A.F()
Now, if you add class C with new, it will behave the same as B. If you add class D with override, then F becomes polymorphic:
class C : A
{
public new void F() { }
}
class D : A
{
public override void F() { }
}
// Later
C c1 = new C();
c1.F(); // will call C.F()
A c2 = new C();
c2.F(); // will call A.F()
D d1 = new D();
d1.F(); // will call D.F()
A d2 = new D();
d2.F(); // will call D.F()
See this fiddle.
No, the default behaviour is exactly the same as if you use new, other than whether the warning is given. In my experience you more often actually want to specify override instead of new, as it's usually just a case of forgetting to explicitly override.
If you really do want a completely separate method, and if you've got the option of using a different name instead, I'd take that approach. Having one method hiding another usually reduces readability significantly IMO. It's not too bad if the purpose is to just give a more specific return type (and you make sure the more weakly typed method returns the same value), but that's a pretty rare case.
This is just warning. Code will work. In some circumstance, this warning can lead to some problem.
use new keyword with the method which you are calling from the base class.
class A
{
public virtual void F() { }
}
class B : A
{
new public void F() { }
}
Reference
https://msdn.microsoft.com/en-us/library/435f1dw2.aspx
https://msdn.microsoft.com/en-us/library/aa691135(v=vs.71).aspx

Multiple inheritance problem in C#

This question came to my mind while I
am reading the post Why doesn't C#
support multiple inheritance?
from MSDN Blog.
At first look at the following code:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class A
{
int num;
public A()
{
num = 0;
}
public A(int x)
{
num = x;
}
public override int GetHashCode()
{
return num + base.GetHashCode();
}
}
class B : A
{
int num;
public B()
{
num = 0;
}
public B(int x)
{
num = x;
}
public override int GetHashCode()
{
return num + base.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
Console.Write(a.GetHashCode() + " " + b.GetHashCode());
Console.Read();
}
}
}
Object class is the ultimate base class of all classes. So it is the base class of A and B both in my program and also make A as a base class of B. So B has now two base class, one is A and another is Object. I override one method GetHashCode() of Object Class in class A and B both. But in class B, base.GetHashCode() method returns the return value of GetHashCode() method of class A. But I want this value from Object class. How can I get that?
B has only one base class, and that is A. A has one base class, and that is object. There is no multiple inheritance; object is only inherited by classes that don’t already inherit from something else.
If you still think you need to call object.GetHashCode(), there is a very hacky workaround to do this in the question How to invoke (non virtually) the original implementation of a virtual method?.
You could write a protected instance method in class A that exposes GetHashCode() from Object. Then call that protected method in class B.
No Class B merely has one base class, class A.
To understand, class A really should be written as:
class A : Object
But since that is required, it can be left off.
This may help you: http://itpian.com/Coding/5191-cant-v-have-Multiple-Inheritances-in-C-sharp---------.aspx
Yes, this doesn't relate to multiple inheritance at all (incidentally, I miss private inheritance more than multiple inheritance). This question is also quite a horrible thing to think about.
If you have control of class A, then fine:
class A
{
/*elide the stuff you already have*/
protected int GetBaseHashCode()
{
return base.GetHashCode();
}
}
class A : B
{
/*elide stuff already in example*/
public override int GetHashCode()
{
return num + GetBaseHashCode();
}
}
If you do not:
public class B : A
{
private static readonly DynamicMethod GRANDPARENT_GET_HASH_CODE;
static B()
{
MethodInfo gpGHC = typeof(object).GetMethod("GetHashCode", BindingFlags.Public | BindingFlags.Instance);
GRANDPARENT_GET_HASH_CODE = new DynamicMethod("grandParentGHC", typeof(int), new Type[] { typeof(object) }, typeof(object));
ILGenerator il = GRANDPARENT_GET_HASH_CODE.GetILGenerator();
il.Emit(OpCodes.Ldarg, 0);
il.EmitCall(OpCodes.Call, gpGHC, null);
il.Emit(OpCodes.Ret);
}
private int num;
public B()
{
num = 0;
}
public B(int x)
{
num = x;
}
public override int GetHashCode()
{
return num + (int)GRANDPARENT_GET_HASH_CODE.Invoke(null, new object[]{this});
}
}
Frankly, I would put that code in the category of "let us never speak of it again". I assume this is relating to some more general principle, since the hashcodes here are useless anyway, but I'm not sure what that more general principle is. Certainly it can sometimes be annoying when something is hidden from deriving classes we want to get at, but it can be much worse when the opposite happens.
Back in the days of VB6, coders in that language would often have to do rather nasty stuff involving getting the memory address of the v-table used for virtual call lookup, altering the memory protection, and then tweaking the bytes stored there by hand, because in "protecting" users from implementation details they kept some vital things away from them (you could not create enumerators without this technique, only pass on those for other objects).
Thank goodness we are not "protected" to that extent in C#. If I ever have to write code like the answer I gave above for a real project, I'm going to need a few drinks to recover later that evening.
Getting a hash of the base Object class is irrelevant to the purpose of the method. The whole point of GetHashCode() is to generate a unique (as possible) identity value based on the specific type and state of the object.
The GetHashCode() method uses a default hashing algorithm that can be used to determine instance identity and uniqueness, though uniqueness is not guaranteed. The default algorithm uses the state of the object to generate the hash.
More information: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx
I'm afraid you are mixing normal inheritance with multiple inheritance. Multiple inheritance meand that you have 3 classes A is subclass of B and C but neither B is subclass of C nor C is subclass of B.
Normal inheritance does allow chaining like A is subclass of B which is subclass of C. If you call method it can walk through the classes and check which method to call (in reality it does not check classes one by one). Here B is subclass of A which is subclass of Object. Object happens to have (virtual) method GetHashCode - by overloading it in subclass. The Object method is hidden and (without tricks) cannot be used.
You should consider an alternative to calling Object.GetHashCode(). Here's why (from MSDN Library):
The default implementation of the
GetHashCode method does not guarantee
unique return values for different
objects. Furthermore, the .NET
Framework does not guarantee the
default implementation of the
GetHashCode method, and the value it
returns will be the same between
different versions of the .NET
Framework. Consequently, the default
implementation of this method must not
be used as a unique object identifier
for hashing purposes.

Why does this polymorphic C# code print what it does?

I was recently given the following piece of code as a sort-of puzzle to help understand Polymorphism and Inheritance in OOP - C#.
// No compiling!
public class A
{
public virtual string GetName()
{
return "A";
}
}
public class B:A
{
public override string GetName()
{
return "B";
}
}
public class C:B
{
public new string GetName()
{
return "C";
}
}
void Main()
{
A instance = new C();
Console.WriteLine(instance.GetName());
}
// No compiling!
Now, after a long, long chat with the other developer who presented the puzzle, I know what the output is, but I won't spoil it for you. The only issue I'm really having is how we get to that output, how the code steps through, what's inheriting what, etc.
I thought C would be returned as that seems to be the class that is defined. Then I went through my head as to whether B would be returned because C inherits B - but B also inherits A (which is where I got confused!).
Question:
Could anyone explain how polymorphism and inheritance play their part in retrieving the output, eventually displayed on screen?
The correct way to think about this is to imagine that every class requires its objects to have a certain number of "slots"; those slots are filled with methods. The question "what method actually gets called?" requires you to figure out two things:
What are the contents of each slot?
Which slot is called?
Let's start by considering the slots. There are two slots. All instances of A are required to have a slot we'll call GetNameSlotA. All instances of C are required to have a slot we'll call GetNameSlotC. That's what the "new" means on the declaration in C -- it means "I want a new slot". Compared to the "override" on the declaration in B, which means "I do not want a new slot, I want to re-use GetNameSlotA".
Of course, C inherits from A, so C must also have a slot GetNameSlotA. Therefore, instances of C have two slots -- GetNameSlotA, and GetNameSlotC. Instances of A or B which are not C have one slot, GetNameSlotA.
Now, what goes into those two slots when you create a new C? There are three methods, which we'll call GetNameA, GetNameB, and GetNameC.
The declaration of A says "put GetNameA in GetNameSlotA". A is a superclass of C, so A's rule applies to C.
The declaration of B says "put GetNameB in GetNameSlotA". B is a superclass of C, so B's rule applies to instances of C. Now we have a conflict between A and B. B is the more derived type, so it wins -- B's rule overrides A's rule. Hence the word "override" in the declaration.
The declaration of C says "put GetNameC in GetNameSlotC".
Therefore, your new C will have two slots. GetNameSlotA will contain GetNameB and GetNameSlotC will contain GetNameC.
We've now determined what methods are in what slots, so we've answered our first question.
Now we have to answer the second question. What slot is called?
Think about it like you're the compiler. You have a variable. All you know about it is that it is of type A. You're asked to resolve a method call on that variable. You look at the slots available on an A, and the only slot you can find that matches is GetNameSlotA. You don't know about GetNameSlotC, because you only have a variable of type A; why would you look for slots that only apply to C?
Therefore this is a call to whatever is in GetNameSlotA. We've already determined that at runtime, GetNameB will be in that slot. Therefore, this is a call to GetNameB.
The key takeaway here is that in C# overload resolution chooses a slot and generates a call to whatever happens to be in that slot.
It should return "B" because B.GetName() is held in the little virtual table box for the A.GetName() function. C.GetName() is a compile time "override", it doesn't override the virtual table so you can't retrieve it through a pointer to A.
Easy, you only have to keep the inheritance tree in mind.
In your code, you hold a reference to a class of type 'A', which is instantiated by an instance of type 'C'. Now, to resolve the exact method address for the virtual 'GetName()' method, the compiler goes up the inheritance hierarchy and looks for the most recent override (note that only 'virtual' is an override, 'new' is something completely different...).
That's in short what happens. The new keyword from type 'C' would only play a role if you would call it on an instance of type 'C' and the compiler then would negate all possible inheritance relations altogether. Strictly spoken, this has nothing to do at all with polymorphism - you can see that from the fact that whether you mask a virtual or non-virtual method with the 'new' keyword doesn't make any difference...
'New' in class 'C' means exactly that: If you call 'GetName()' on an instance of this (exact) type, then forget everything and use THIS method. 'Virtual' in contrary means: Go up the inheritance tree until you find a method with this name, no matter what the exact type of the calling instance is.
OK, the post is a bit old, but it's an excellent question and an excellent answer, so I just wanted to add my thoughts.
Consider the following example, which is the same as before, except for the main function:
// No compiling!
public class A
{
public virtual string GetName()
{
return "A";
}
}
public class B:A
{
public override string GetName()
{
return "B";
}
}
public class C:B
{
public new string GetName()
{
return "C";
}
}
void Main()
{
Console.Write ( "Type a or c: " );
string input = Console.ReadLine();
A instance = null;
if ( input == "a" ) instance = new A();
else if ( input == "c" ) instance = new C();
Console.WriteLine( instance.GetName() );
}
// No compiling!
Now it's really obvious that the function call cannot be bound to a specific function at compile time. Something must be compiled however, and that information can only depend on the type of the reference. So, it would be impossible to execute the GetName function of class C with any reference other than one of type C.
P.S. Maybe I should've used the term method in stead of function, but as Shakespeare said: A function by any other name is still a function :)
Actually, I think it should display C, because new operator just hides all ancestor methods with the same name. So, with methods of A and B hidden, only C remains visible.
http://msdn.microsoft.com/en-us/library/51y09td4%28VS.71%29.aspx#vclrfnew_newmodifier

Categories

Resources