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 3 years ago.
Improve this question
A question I'm having trouble finding the answer to: When my class is instantiated, in what order are it's members instantiated.
For example, can I set a member to the value of a member lower in the declaration order? (See code example.)
// Can I do the following:
class foo
{
int A = B;
int B = 12;
}
// And this, for class types:
class bar
{
foo X = Y;
foo Y = new foo();
}
The order of field instantiation does not matter in this case. What matters is that you cannot use non-static field, method or property in the field initializer. So, it doesn't matter if you do:
class Foo
{
int A = B;
int B = 12;
}
or the opposite order
class Foo
{
int B = 12;
int A = B;
}
Your code will not compile anyway. You will get A field initialize cannot reference the non-static field, method, or property 'Foo.B' error.
So, you shouldn't worry about the order because this situation can never occur.
You just can't do it.
You will get the following compilation error :
Error CS0236 A field initializer cannot reference the non-static field, method, or property 'Program.foo.A' Test C:\Users\sebas\source\repos\Test\Test\Program.cs 14 Active
I you extend the question to static field, they are executed from the first to the latest one.
It can easily be tested with the following code :
class foo
{
public static int A = foo.B;
public static int B = 3;
public static int C = foo.B;
}
static void Main(string[] args)
{
Console.WriteLine(foo.A);
Console.WriteLine(foo.B);
Console.WriteLine(foo.C);
Console.ReadLine();
}
The result will be :
0
3
3
Anyway. Even if it was working, I would suggest that you just use a constructor. You will gain in maintainability.
Despite the bad example, it's worth understanding how initialization actually works. The draft C# 6.0 Spec has this to say about it:
The default value initialization described in Field initialization occurs for all fields, including fields that have variable initializers. Thus, when a class is initialized, all static fields in that class are first initialized to their default values, and then the static field initializers are executed in textual order. Likewise, when an instance of a class is created, all instance fields in that instance are first initialized to their default values, and then the instance field initializers are executed in textual order.
Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#field-initialization
Related
To further explain: i have a class let's say A, with a property of type let's say X; what i would like to do is to be able to instantiate A somewhere and assign the attribute using the instance without accessing the property itself or using methods, and possibly doing some other operation. Something like this:
public class A
{
private X _inside; //it actually can be public also
private DateTime _timeStamp;
public A() {X = new X();}
}
A anInstance = new A();
X aParameter = new X();
anInstance = aParameter
aParameter should be set to the _inside property of anInstance, while also assign DateTime.UtcNow to _timeStamp. Is it possible to do so? I am aware that doing so through a method or get and set is way easier, i'd get the same result and is possibly more efficient, but i would like to do so.
Also, I don't know if this thing has a specific name, therefore this question may be a duplicate; I am highlighting this because i had a problem with circular headers once but i didn't know that they were called so and my question was marked as a duplicate (not an english native seaker), which is not a problem as long as pointing we have an answer.
Anyway, thanks in advance!
Edit lexicon fixed as suggested in the comments
I believe what you're asking for is similar to VB classic's default properties1. Imagine that C# (and .NET in general) had adopted this concept, and that we're allowed to declare one2:
//Not legal c#
public class A
{
public default A _inside {get;set; }
private DateTime _timeStamp;
public A() {}
}
It's perfectly legal for classes to have properties of their own types, and introducing restrictions just for these default properties to avoid the problems I'm about to talk about are worse than disallowing the existence of these default properties3.
So you now have the code:
A anInstance = new A();
A aParameter = new A();
anInstance = aParameter;
Pop quiz - what does line 3 do? Does it assign _inner? Of does it reassign anInstance?
VB classic solved this issue by having two different forms of assignment. Set and Let. And it was a frequent source of bugs (Option Explicit being off by default didn't help here either).
When .NET was being designed, the designers of both C# and VB.Net looked at this and said "nope". You can have indexers (c#)/default properties (VB.Net) but they have to have additional parameters:
public class A
{
private Dictionary<int,A> _inner = new Dictionary<int,A>();
public A this[int i] {
get { return _inner[i]; }
set { _inner[i] = value; }
}
private DateTime _timeStamp;
public A() {}
}
And now we can disambiguate the different assignments in a straightforward manner:
A anInstance = new A();
A aParameter = new A();
anInstance = aParameter;
anInstance[1] = aParameter;
Lines 3 and 4 are, respectively, reassigning the reference and reassigning the property value.
1VB.Net does have default properties but, as discussed later, they're not precisely the same as VB classic's.
2Note that we can't assign it an instance in the constructor now - that would lead to a stack overflow exception since constructing any instance of A would require constructing an additional instance of A which would require constructing an additional instance of A which would...
3A concrete example of this would be a Tree class that has subtrees and a SubTree class that inherits from Tree and has a Parent property of tree. If that were the "default property" for the SubTree class you'd encounter these same property/reference assignment issues discussed lower down if trying to assign a parent of a subtree of a subtree.
Which basically means that you have to disallow default properties of both the actual type in which it's declared and any type to which it's implicitly convertible, which includes all types in its inheritance hierarchy.
Did you think about inheritance?
public class A : X
{
private DateTime _timeStamp;
public A() : base() {}
}
A anInstance = new A();
X aParameter = new X();
anInstance = (A)aParameter;
This question already has answers here:
How do I assign by "reference" to a class field in C#?
(3 answers)
C# reference member variable
(5 answers)
Closed 5 years ago.
Sorry, this is a basic question, which I cannot find an answer to.
I have to write some code in C#, and I need to create a class member variable that is a reference.
In C++ this code would be
public class MyClass
{
MyClass(int& m_var): mVar(m_var){}
int& mVar;
}
However I cannot seem to do this in C#
I can create a constructor with a reference parameter using
MyClass(ref int m_var)
But I cannot create a reference member variable using
class MyClass
{
MyClass(ref int m_var)
{
mVar = m_var;
}
ref int mVar;
}
Because the line:
ref int mVar;
Gives me the error: 'Invalid Token 'ref' in class, struct, or interface member declaration.
Why is this? Why did C# take away the functionality to create reference member variables?
int is just a placeholder for another class here
Whoa there! int is not just "another class". int is a value type. You can't have a field that's a reference to it. You can have a ref parameter. In C#7 you can have ref returns and locals, but still not fields.
In the CLR, int is critically different from classes in exactly the area we're talking about here. x is an int on what we'll figuratively call "the stack", since I don't feel like looking up how they actually implemented it. In C, I seem to recall describing that as a stack variable:
int x = 0;
List<T> is a class. y, here, is a "stack variable" which is a rebindable reference to an object on the "heap":
var y = new List<int>();
If you're talking about sharing references to reference types -- any class -- in C# that's easy: It's always a reference.
public class C {
// x is passed by value. It is the value of a reference. Seriously, it is.
public C(List<String> x) {
List = x;
}
public List<String> List { get; set; }
}
...
var list = new List<String>();
var x = new C(list);
var y = new C(list);
x.List and y.List are the same object, at least until you assign a new object to one of them -- C# references, unlike C++ references (at least as of C++98; I haven't kept up since 2006) are "rebindable".
The way to do this is to write a simple class with an int property, and share a reference to an instance of that. where T : struct restricts T to be a struct rather than a class. In CLR-land, that means "value type" rather than "reference type".
public class Reference<T> where T : struct
{
public Reference(T t) {
Value = t;
}
public T Value { get; set; }
}
class MyClass
{
MyClass(Reference<int> ref)
{
_ref = ref;
}
Reference<int> _ref;
}
Why did C# take away the functionality to create reference member variables?
They didn't "take it away"; they didn't abduct an infant C++ compiler and cut its toes off. They just didn't think it was a good idea to do that in C#, and they were right. C# isn't C and it isn't meant to be C. Dennis Ritchie designed C to be used by people like Ken Thompson; Anders Hejlsberg explicitly designed C# to be used by the rest of us, who are much more easily confused.
This is built deeply into .NET:
The CLR type system however does not allow for fields that are aliases to other variables
(That's an old essay; C#7 now does support the additional uses of ref that the CLR supported all along).
New C# programmers already have more than enough trouble with ref and reference types. Just recently I saw code in a question here much like this:
public void F(ref List<int> x) { ... }
The fellow who wrote that code just wanted to pass in a List<int> without creating an expensive copy of it.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm looking for a differences between declarations to define an integer numbers and declarations for a fields.
EXAMPLE: Declaration 'int b;' can be declaration for the inetger number b or it can be the declaration for the private field b. As it looks like, it depends on where this declaration is situated.
I know, that typical declaration to define a field is 'private string field;'
In the code below in the class MyClass I can't declare the integer numbers, but just the fields. Why?
I wrote 'int b;' because I wanted to declare the integer number b, but I got the field b. Visual Studio shows me, that 'b' is the field.
using System;
class MyClass
{
int b;
public static int x = 20;
public static int y;
public static int z = 25;
public MyClass(int i)
{
x = i;
y = i;
z = i;
}
}
class MyClient
{
public static void Main()
{
Console.WriteLine("{0},{1},{2}", MyClass.x, MyClass.y, MyClass.z);
MyClass mc = new MyClass(25);
Console.WriteLine("{0},{1},{2}", MyClass.x, MyClass.y, MyClass.z);
Console.ReadLine();
}
}
All fields are variables, but not all variables are fields.
From the documentation,
A field is a variable of any type that is declared directly in a class or struct. Fields are members of their containing type.
Or, more simply, fields are variables that are associated only with the class or object itself, not with a specific method.
Thus, when you have int b = 7;, it is technically correct to call it a variable, but it's more specific to call it a field. It's the same way that it's technically correct to simply call a Porsche Boxter a car - it is, in fact, a car, but it's more descriptive (and, therefore, potentially more useful) to call it a Boxter.
Note in particular that the definition of a field says absolutely nothing about what else is included in the class. A field is a field regardless of what other content you do (or don't) have in the class (so, for example, the fact that MyClass doesn't have a Main method is completely irrelevant).
Fields can be distinguished from a local variable, which is declared inside a method and is associated only with that particular method. For example:
public class MyClass {
public int a = 10; // This is a field
int b = 20; // Also a field
public void MyMethod() {
int c = 30; // This is a local variable, NOT a field
}
}
Note, in particular, that c is not "declared directly in a class or struct" - it's declared inside a method. Thus, by definition it's not a field.
Based on the wording in your question, I feel that your understanding of using the words "variables" and "field" is misguided.
You seem to be calling:
"variables" as private fields
"fields" as public fields
Take a look at the below code block, to help:
class MyClass
{
int b = 7; // this is a private field
private int c = 8; // this is a private field
public int d = 10; // this is a public field
}
In addition, from the code above, you can now understand the reason why you are unable to access b. It is due to the private access modifier that is assumed. You need to change it to a public field.
So, what you'll want to get your code up and going quickly is change:
int b = 7;
to
public int b = 7;
and then you can change
public static void Main()
{
Console.WriteLine("{0},{1},{2}", MyClass.x, MyClass.y, MyClass.z);
MyClass mc = new MyClass(25);
Console.WriteLine("{0},{1},{2}", MyClass.x, MyClass.y, MyClass.z);
Console.ReadLine();
}
to
public static void Main()
{
Console.WriteLine("{0},{1},{2}", MyClass.x, MyClass.y, MyClass.z);
MyClass mc = new MyClass(25);
Console.WriteLine("{0},{1},{2}", MyClass.x, MyClass.y, MyClass.z);
Console.WriteLine("{0}", mc.b);
Console.ReadLine();
}
Take special note that public fields should usually be avoided in favor for properties, you can read more about that by doing a few searches online.
Additional Resources
Fields (C# Programming Guide)
static (C# Reference)
Static Classes and Static Class Members (C# Programming Guide)
Properties (C# Programming Guide)
This question already has answers here:
Order of static constructors/initializers in C#
(4 answers)
Closed 8 years ago.
I'm curious of the C# spec says anything about the order of initializing static field's in C# 5 (.net4). For instance:
public class Test
{
public static readonly string A = "hi";
public static readonly string B = "bye";
public static readonly string DEFAULT = A;
}
In testing (Mono 2.x) they seem to be initialized in the order they appear in code. eg. As is, DEFAULT will have the value "hi", but if I move the definition for DEFAULT above A and B, it will be assigned NULL because A hasn't been assigned yet.
Is there a guarantee that the variables are initialized in order? Or is it up to the compiler?
Thanks.
It is in the order that they appear in. See here.
The static field variable initializers of a class correspond to a
sequence of assignments that are executed in the textual order in
which they appear in the class declaration.
Also, when you have a static constructor:
If a static constructor (Section 10.11) exists in the class,
execution of the static field initializers occurs immediately prior to
executing that static constructor. Otherwise, the static field
initializers are executed at an implementation-dependent time prior to
the first use of a static field of that class.
This question is an extension of Cristi Diaconescu's about the illegality of field initializers accessing this in C#.
This is illegal in C#:
class C
{
int i = 5;
double[] dd = new double[i]; //Compiler error: A field initializer cannot reference the non-static field, method, or property.
}
Ok, so the reasonable explanation to why this is illegal is given by, among others, Eric Lippert:
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.
Also, the C# specifications are pretty straightforward (up to a point):
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.
So my question is: what does "through a simple-name" mean?
Is there some alternative mechanism where this would be legal? I am certain that almost every word in the specification is there for a very specific reason, so what is the reason of limiting the illegality of this particular code to references through simple names?
EDIT: I've not worded my question too well. I'm not asking for the definition of "simple-name", I am asking about the reason behind limiting the illegality to that particular scenario. If it is always illegal to reference any instance member in any which way, then why specify it so narrowly? And if its not, then what mechanism would be legal?
It isn't possible, in the general case, to determine whether an expression refers to the object being constructed, so prohibiting it and requiring compilers to diagnose it would require the impossible. Consider
partial class A {
public static A Instance = CreateInstance();
public int a = 3;
public int b = Instance.a;
}
It's possible, and as far as I know perfectly valid, even if it a horrible idea, to create an object with FormatterServices.GetUninitializedObject(typeof(A)), set A.Instance to that, and then call the constructor. When b is initialised, the object reads its own a member.
partial class A {
public static A CreateInstance() {
Instance = (A)FormatterServices.GetUninitializedObject(typeof(A));
var constructor = typeof(A).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
var helperMethod = new DynamicMethod(string.Empty, typeof(void), new[] { typeof(A) }, typeof(A).Module, true);
var ilGenerator = helperMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Call, constructor);
ilGenerator.Emit(OpCodes.Ret);
var constructorInvoker = (Action<A>)helperMethod.CreateDelegate(typeof(Action<A>));
constructorInvoker(Instance);
return Instance;
}
}
static class Program {
static void Main() {
Console.WriteLine("A.Instance = (a={0}, b={1})", A.Instance.a, A.Instance.b);
}
}
You can only get compiler errors for what's detectable at compile time.
According to the documentation:
A simple-name consists of a single identifier.
I suppose they clarify this because this.i is equivalent to i within a class method, when no variable named i is in scope. They've already forbade the use of this outside of an instance method:
class C
{
int i = 5;
double[] dd = new double[this.i];
//Compiler error: Keyword 'this' is not available in the current context.
}
If this language wasn't there, some might read this as meaning you could reference instance variables simply by omitting the keyword this.
The best alternative is to use a constructor:
class C
{
int i = 5;
double[] dd;
C()
{
dd = new double[i];
}
}
You can also do this:
class C
{
public int i = 5;
}
class D
{
double[] dd = new double[new C().i];
}
Thanks to the fact that the two members are in different classes, the order in which they are initialized is unambiguous.
You can always do really messed up stuff when unmanaged code comes into play. Consider this:
public class A
{
public int n = 42;
public int k = B.Foo();
public A()
{
}
}
public class B
{
public static unsafe int Foo()
{
//get a pointer to the newly created instance of A
//through some trickery.
//Possibly put some distinctive field value in `A` to make it easier to find
int i = 0;
int* p = &i;
//get p to point to n in the new instance of `A`
return *p;
}
}
I spent a bit of time trying to actually implement this (for kicks) but gave up after a bit. That said, you can get a pointer to the heap and then just start looking around for something that you can recognize as an instance of A and then grab the n value from it. It would be hard, but it is possible.
I think you are just misreading the last sentence. The spec flatly states an instance field initializer cannot reference the instance being created. It is then simply citing examples. You cannot use this and for the same reason you cannot use a "simple-name" because a simple name access implicitly uses this. The spec is not narrowing the cases. It simply calling out some specific constructions that are illegal. Another one would be using base to access a protected field from a base class.