I have the following code :
struct Person
{
public readonly int x;
public Person( int x )
{
this.x = x;
}
}
class Program
{
static void Main(string[] args)
{
Person p = new Person();
Console.Write(p.x);
}
}
This code work well.Why? Did overriding default constructor not be applied to structs ?
Did using a parameterized constructor override the default one or not ?
You didn't override the default constructor; you just provided an overload which accepts one parameter. Unlike classes, having a parameterized constructor for a struct doesn't mean that the default constructor won't be automatically generated. The C# compiler automatically provides a default, parameterless constructor for structs, and it does not allow you to override it with your own.That's simply the nature of structs.
From Using Structs (C# Programming Guide)
It is an error to define a default (parameterless) constructor for a struct. It is also an error to initialize an instance field in a struct body. You can initialize struct members only by using a parameterized constructor or by accessing the members individually after the struct is declared. Any private or otherwise inaccessible members can be initialized only in a constructor.
If you really want to require users of your data type to call a custom constructor, you'll have to use a class instead.
Structs will always have a default parameterless constructor which you cannot overrride.
MSDN explains a little. This (and other) limitations are there because structs are value types. If you need to use them like objects, use objects :)
http://msdn.microsoft.com/en-us/library/aa288208%28v=vs.71%29.aspx
Structs cannot contain explicit parameterless constructors. Struct members are automatically initialized to their default values
Some good explanation
Why can't I define a default constructor for a struct in .NET?
In your code, you are not calling the constructor you created, but rather the default constructor.
To call the constructor you overrode, try the following code:
struct Person
{
public readonly int x;
public Person( int x )
{
this.x = x;
}
}
class Program
{
static void Main(string[] args)
{
int v = 9;
Person p = new Person(v);
Console.Write(p.x); // will output '9'
}
}
Related
In C# documentation and particulary Structs I found these sentences which I can't understand:
If the struct instance constructor doesn't specify a constructor initializer, the this variable corresponds to an out parameter of the struct type, and similar to an out parameter, this must be definitely assigned (Definite assignment) at every location where the constructor returns. If the struct instance constructor specifies a constructor initializer, the this variable corresponds to a ref parameter of the struct type, and similar to a ref parameter, this is considered definitely assigned on entry to the constructor body.
I want to know what is the relation between this keyword in constructors and, the ref and out keywords.
If you're not familiar with the terms used in the documentation this might seem a bit convoluted, but let's take it step by step.
Basic rule is: Struct constructors must ensure all fields of a struct instance has been initialized. No exceptions.
Also, relevant for the following is that a "constructor initializer" means you're chaining calls through multiple constructors:
public YourStruct(...) : this(...)
^----+----^
|
+-- constructor initializer
For reference, out and ref parameters to methods:
public void Test(out int x) { ... }
public void Test(ref int x) { ... }
means that the out int x parameter has to be fully initialized in the method, and is considered unassigned at the start of the method. See the out parameter modifier documentation for reference.
Whereas the ref int x parameter is considered assigned at the start of the method, and the method can change it but does not have to. See the ref keyword for more information.
So, let's take the rest of the documentation now.
If you do not have a constructor initializer for your constructor, then it means your constructor has to tackle the basic rule all by itself. This is what it means that it is similar to an out parameter for a method, your constructor has to fully initialize the struct instance before returning.
However, if you do have a constructor initializer, then that constructor also has to fully initialize the struct instance and so by the time your constructor gets to execute, the instance is already fully initialized. In this case, your constructor does not have to initialize all the fields any more but can selectively change only the fields it needs. This is what it means regarding the ref parameter.
Let me give an example:
public struct X
{
public int A;
public int B;
public X(int a, int b)
{
// no constructor initializer, MUST initialize both A and B
A = a;
B = b;
}
}
However:
public struct X
{
public int A;
public int B;
public X(int a)
: this(a, 0)
{
// constructor initializer, DOES NOT have to initialize anything
// you can, though, if you want to change B
B++;
}
public X(int a, int b)
{
// no constructor initializer, MUST initialize both A and B
A = a;
B = b;
}
}
So basically the documentation states:
If you DO NOT have a constructor initializer, the constructor has to fully initialize the this variable, similar to how an out parameter works
If you DO have a constructor initializer, the constructor DOES NOT have to do anything, and you can consider the this variable similar to a ref parameter instead.
I have a structure as below. I have few problems
Problem1:
struct MyStruct
{
public MyStruct(int a)
{
this.a = a;
this.b = 10;
}
public int a;
public int b;
}
When I remove this.b from MyStruct constuctor it will give me an error "Field must be fully assigned before control is returned to the caller". but in case of class it doesn't occur
Problem2:
struct MyStruct
{
//public MyStruct(int a)
//{
// this.a = a;
// this.b = 10;
//}
//int asd;
//public int MyProperty { get; set; }
public void getImplemen()
{
Console.WriteLine("azsdfa");
}
public int a;
public int b;
}
static void Main(string[] args)
{
MyStruct myStruct ;
myStruct.a = 15;//when I comment this it will give an error
myStruct.b = 15; //when I comment this it will give an error
myStruct.getImplemen();
}
When I change MyStruct myStruct to MyStruct myStruct = new MyStruct ();
it works fine.
why so?
That's just how it goes.
Default constructor initializes every field to a default value, while a constructor with parameters forces you to initialize every field in the struct.
What if you have a default constructor AND one with parameters, you ask? Well, I don't remember. Easy enough to check on your own.
It does not allocate memory for fields:
MyStruct myStruct;
Allocates memory and initialize fields in constructor:
MyStruct myStruct = new MyStruct();
If you does not allocate memory for a variable then you can not assign a value to the fields. Сonstructor allocate memory and initializes fields (you need initialize fields in constructor before control is returned to the caller).
you should refer to https://msdn.microsoft.com/en-us/library/aa288471(v=vs.71).aspx
you need to create the instance of your struct before using it.
The difference is that structs are value types while classes are reference types. When a value type object is created, memory space will be allocated to store the value, thus its member variable cannot be null, whilst class member variables can be null. Hence, the compiler only complains when struct member variables are not assigned to.
Remember the thumb rule for Structs: All fields must be initialized. Values can be provided by you or default ones.
For Question 1:
When you initialize struct with 'new' (without parameters), all fields in it are initialized to default type values (0 for int, null for string etc). Since you are using parameterized constructor compiler does not use default one and hence you get error if you don't initialize field 'b'. You can still make this work as below:
public MyStruct(int a) : this()
{
this.a = a;
}
For Question 2:
Recall the thumb rule I mentioned in the beginning. So you either use default constructor with 'new' initialization or set field values in calling code.
Quick suggestion: Please do not use public fields in class/struct. Use properties to encapsulate them.
I have a next code:
struct T
{
public T(int u)
{
this.U = 10; //Errors are here
}
public int U { get; private set; }
}
C# compiler give me a pair of errors in stated line:
1) Backing field for automatically implemented property 'TestConsoleApp.Program.T.U' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
2) The 'this' object cannot be used before all of its fields are assigned to
What I do wrong? Help me understand.
From the C# Specification:
10.7.3 Automatically implemented properties
When a property is specified as an automatically implemented property,
a hidden backing field is automatically available for the property,
and the accessors are implemented to read from and write to that
backing field.
[Deleted]
Because the backing field is inaccessible, it can be read and written
only through the property accessors, even within the containing type.
[Deleted]
This restriction also means that definite assignment of struct types
with auto-implemented properties can only be achieved using the
standard constructor of the struct, since assigning to the property
itself requires the struct to be definitely assigned. This means that
user-defined constructors must call the default constructor.
So you need this:
struct T
{
public T(int u)
: this()
{
this.U = u;
}
public int U { get; private set; }
}
Well, for a start you're creating a mutable struct - that's almost always a really bad idea. Mutable structs can sometimes behave in ways you don't expect. Okay, it's only privately mutable, but the fact that you've written code to mutate it is a bad sign.
The reason for the second error is that you can't use any properties or methods of the struct until all fields have been assigned, so you need to chain to the implicit parameterless constructor:
public T(int u) : this()
{
this.U = 10;
}
The compiler requires that any constructor leaves all the fields definitely assigned (which is why you were getting the first error before; the compiler doesn't "know" that the property assigns the field a value) - by chaining to this(), you're making sure that by the time you get to your constructor body, all the fields are already definitely assigned, and you don't need to worry about it any more.
However, unless you actually want to allow mutation, I suggest you just make it a genuinely read-only property:
struct T
{
private readonly int u;
public T(int u)
{
this.u = 10;
}
public int U { get { return u; } }
}
Now it's more obvious that you don't want to mutate it even within the struct itself.
Add a call to the default constructor:
public T(int u) : this()
{
this.U = 10;
}
you have to use the default constructor here:
struct T
{
public int U { get; private set; }
public T(int u) : this()
{
U = 10;
}
}
From C# 6 this is not an issue anymore and it compiles correctly. Look here
I have a next code:
struct T
{
public T(int u)
{
this.U = 10; //Errors are here
}
public int U { get; private set; }
}
C# compiler give me a pair of errors in stated line:
1) Backing field for automatically implemented property 'TestConsoleApp.Program.T.U' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
2) The 'this' object cannot be used before all of its fields are assigned to
What I do wrong? Help me understand.
From the C# Specification:
10.7.3 Automatically implemented properties
When a property is specified as an automatically implemented property,
a hidden backing field is automatically available for the property,
and the accessors are implemented to read from and write to that
backing field.
[Deleted]
Because the backing field is inaccessible, it can be read and written
only through the property accessors, even within the containing type.
[Deleted]
This restriction also means that definite assignment of struct types
with auto-implemented properties can only be achieved using the
standard constructor of the struct, since assigning to the property
itself requires the struct to be definitely assigned. This means that
user-defined constructors must call the default constructor.
So you need this:
struct T
{
public T(int u)
: this()
{
this.U = u;
}
public int U { get; private set; }
}
Well, for a start you're creating a mutable struct - that's almost always a really bad idea. Mutable structs can sometimes behave in ways you don't expect. Okay, it's only privately mutable, but the fact that you've written code to mutate it is a bad sign.
The reason for the second error is that you can't use any properties or methods of the struct until all fields have been assigned, so you need to chain to the implicit parameterless constructor:
public T(int u) : this()
{
this.U = 10;
}
The compiler requires that any constructor leaves all the fields definitely assigned (which is why you were getting the first error before; the compiler doesn't "know" that the property assigns the field a value) - by chaining to this(), you're making sure that by the time you get to your constructor body, all the fields are already definitely assigned, and you don't need to worry about it any more.
However, unless you actually want to allow mutation, I suggest you just make it a genuinely read-only property:
struct T
{
private readonly int u;
public T(int u)
{
this.u = 10;
}
public int U { get { return u; } }
}
Now it's more obvious that you don't want to mutate it even within the struct itself.
Add a call to the default constructor:
public T(int u) : this()
{
this.U = 10;
}
you have to use the default constructor here:
struct T
{
public int U { get; private set; }
public T(int u) : this()
{
U = 10;
}
}
From C# 6 this is not an issue anymore and it compiles correctly. Look here
I'm new to the C# world and I can't find a method to declare read only variable in C# (something like declaring "const" variable in c++). Is there one?
I'll give you an example:
...
int f() { return x; } // x is not const member
...
void g() {
int readOnlyVar = f(); // is there a method to declare readOnlyVar as read only or const
// Some code in which I want to restrict access to readOnlyVar to read only
}
There isn't an identical analogue.
The readonly keyword allows the variable value to be mutated, but only in a constructor.
The const keyword means the value cannot mutate and needs to be a compile time constant and can only be one of the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, an enum-type, or a reference-type. (C# 4.0 spec §10.4).
And in c#, readonly only applies to fields and cannot be applied to local variables.
No, there exists no solution for your code-example.
const in C# is for compile-time constants and since your variable gets its value from a function, it's not known at compile-time.
The readonly keyword does kind of what you're looking for, but that's only for member variables in classes (and only allows variables to be set in the constructor of the class).
But, on the other hand, why would you ever need it? If your function is very long, it should be refactored into smaller functions. If it's not very long, then why would you need to enforce a rule like this? Just don't assign to readOnlyVar is probably my best suggestion for you I'm afraid.
There are two ways to set a variable as read only.
public class ClassA
{
private const int I = 5;
private readonly int J = 5;
}
The const keyword will set the value at compile time. The readonly keyword will set the value at construction. So, if you need different values for each instance, use readonly. Otherwise use const.
in c# we having const or readonly keyword to declare a constant.
const
A constant member is defined at compile time and cannot be changed at runtime. Constants are declared as a field, using the const keyword and must be initialized as they are declared. For example;
public class MyClass
{
public const double PI = 3.14159;
}
PI cannot be changed in the application anywhere else in the code as this will cause a compiler error.
readonly
A read only member is like a constant in that it represents an unchanging value. The difference is that a readonly member can be initialized at runtime, in a constructor as well being able to be initialized as they are declared. For example:
public class MyClass
{
public readonly double PI = 3.14159;
}
or
public class MyClass
{
public readonly double PI;
public MyClass()
{
PI = 3.14159;
}
}
Because a readonly field can be initialized either at the declaration or in a constructor, readonly fields can have different values depending on the constructor used. A readonly field can also be used for runtime constants as in the following example:
public static readonly uint l1 = (uint)DateTime.Now.Ticks;
Notes
readonly members are not implicitly static, and therefore the static keyword can be applied to a readonly field explicitly if required.
A readonly member can hold a complex object by using the new keyword at initialization.
readonly members cannot hold enumerations.
credit goes here:
http://www.dotnetspider.com/forum/69474-what-final-c-i-need-detailed-nfo.aspx
This is not a language feature, but you’re not the only person interested in such a feature. You do have some options, though. You might replace your method’s implementation with a class that has readonly member variables. This is a big pain, though, and really explodes the size of your code. (When you write lambdas or use async methods, C# does something similar to lift locals to class fields and turns your lambda or async method into methods on an autogenerated class. We are basically doing the same thing, but manually so that we can set readonly.)
class Scope
{
int x;
int f() => x; // x is not const member
void g()
{
new gImpl(f()).Run();
}
class gImpl
{
readonly int readOnlyVar;
public gImpl(
int readOnlyVar)
{
this.readOnlyVar = readOnlyVar;
}
public void Run()
{
// Some code in which I want to restrict access to readOnlyVar to read only
// error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
readOnlyVar = 3;
}
}
}
Another alternative which requires less code but is still clunky is to abuse a feature of foreach. The foreach keyword does not let you assign to the iteration variable. So you could do something like this:
class Scope
{
int x;
int f() => x;
void g()
{
foreach (var readOnlyVar in new[] { f(), })
{
// Some code in which I want to restrict access to readOnlyVar to read only
// error CS1656: Cannot assign to 'readOnlyVar' because it is a 'foreach iteration variable'
readOnlyVar = 3;
}
}
}
The foreach method makes it easier to use anonymous types, but you could use generics combined with type inference to use anonymous types with the class method.