Achieving Local Runtime Immutability in C# - c#

I currently know of two ways to make an instance immutable in C#:
Method 1 - Compile Time Immutability
void Foo()
{
// Will be serialized as metadata and inserted
// as a literal. Only valid for compile-time constants
const int bar = 100;
}
Method 2 - Readonly Fields
class Baz
{
private readonly string frob;
public Baz()
{
// Can be set once in the constructor
// Only valid on members, not local variables
frob = "frob";
}
}
It would be nice to have a guarantee that, some instance, once instantiated, will not be changed. const and readonly do this to a small degree, but are limited in their scope. I can only use const for compile-time constants, and readonly for member variables.
Is there any way to give a local variable immutability after its initial instantiation (the way readonly works, but on a more general level)?
Scala does this with the var keyword, which declares a new immutable value, which cannot be reassigned to after it gets its initial value:
var xs = List(1,2,3,4,5) // xs is a value - cannot be reassigned to
xs = List(1,2,3,4,5,6); // will not compile

You can't prevent variables from being re-assigned in C# with the exception of fields, by as you have already mentioned using const or readonly.
You could make your own immutable version of any existing mutable type by wrapping it or if it's your own class, re-write it to be immutable but you can't achieve it for variables in a method which is what your question seems to be getting at.
F# has a few options for immutability (the 'let keyword if I'm remembering correctly) that C# doesn't so it might be worth looking at F# if you still want to leverage the power of .NET but with complete immutability.

If the wrapper is static it cannot be overwritten. This does sacrafice compile time checking on variable names and type safety.
public static class ReadOnly
{
private static readonly Dictionary<string, object> values = new Dictionary<string, object>();
public static bool SetValue(string name, object data)
{
if (values.ContainsKey(name))
return false;
values[name] = data;
return true;
}
public static object GetValue(string name)
{
return values[name];
}
}
ReadOnly.SetValue("xs", 1);
ReadOnly.SetValue("xs", 1); // will crash

Related

What is the real difference between a static member and a constant in C#?

I'm learning C#,and now i'm trying to understand static members and constants.Which is the best way to declare a constant?
This way?
class Myclass
{
public const double G=9.8;
}
Or
class Myclass
{
private static double G{get;set;}
static MyClass()
{
G=9.8;
}
}
I've asked this question because,with the 2 ways i access the membre with the same code:
Console.WriteLine(Myclass.G);
constant:
Constant fields are defined at the time of declaration in the code
snippet, because once they are defined they can't be modified. By
default a constant is static, so you can't define them static from
your side.
It is also mandatory to assign a value to them at the time of
declaration otherwise it will give an error during compilation of the
program snippet. That's why it is also called a compile-time constant.
Explanation:
Consider ff. code:
void Sum(int j)
{
const int i = 9, k = 2;
const int A = i + k;
}
This will produce a result of 11, without showing any error since we already declared it at the initial point of declaration.
But how about:
void Sum(int j)
{
const int i = 9, k = 2;
//const int A = i + k;
Const int B = i + j;
}
This code snippet will take you toward a compile-time error, because there is no initialization, since it's evaluated at run time.
Points to Remember
Compile-time constant
Can't be declared static
Can't be modified or changed
Can be of any type of Access Modifier
Local scope
Needs to get initialized
Declared at the time of declaration
Static
The static keyword is used to declare a static member. If we are
declare a class as a static class then in this case all the class
members must be static too. The static keyword can be used effectively
with classes, fields, operators, events, methods and so on
effectively.
Consider ff. code:
class ReadOnly
{
static int i = 11;
public static void disp()
{
Console.WriteLine(i);
}
}
Explanation:
This code will show no error and produce a result (11), since we declared its value to be static at the time of declaration. So we can access it depending on our use in the program.
But how about this:
class ReadOnly
{
int i = 9;
public static void disp()
{
Console.WriteLine(i);
}
}
This snippet above will show an error, because we didn't declare a value for the static and we are trying to access it within a method. We can't do that.
Points to Remember:
Can't be used with indexers
Works with constructors too
By default it is private
Can be parameterized or public too
If its applied to a class then all the class members need to be static
You can read more about above explanation here: constant vs readonly vs static
Additional note for static methods.
Consider ff. code:
public class SomeClass {
public string SomeMethod() {
return "Hello, World.";
}
}
When you want to Access SomeMethod of SomeClass, you need to instantiate SomeClass first:
var some = new SomeClass();
string result = some.SomeClass(); //this will set result as "Hello, World."
Compared to a static method:
public class SomeClass {
public static string SomeMethod() {
return "Hello, World.";
}
}
When accessing SomeMethod, you don't need to instantiate SomeClass. You can access it directly by:
string result = SomeClass.SomeMethod(); //this will give "Hello, World."
Which is the best way to declare a constant?
Its not the best, its the only way: const double G = 9.8;.
Or (...) static double G { get; set; }
Thats not a constant! Constant means constant: 1 is a constant, 'c'is a constant, PI is a constant... they represent values that don't change, ever!. Your second implementation of G can change, therefore its not a constant.
Also, its important you notice that constants are known at compile time, there is no evaluation needed at runtime.
This is the reason why any reference type const (expect string which has specific compiler support through string literals) can only be initialized to null, any other option would need to be evaluated at runtime.
Its also the reason why only a finite set of value types can be declared as const too. All of them are existing types in the framework and.. surprise, surprise, they all have compiler literal constant support: 1, 'c', 9.8 or 0.25M but not 01/01/2017 (how else would the compiler know the values before runtime?).
Another interesting question you didn't make is: what about static readonly?
You can think of static readonly as "the poor man's" const. Its often used to circumvent the limitations const offers concerning what types and initializing values are allowed.
It is almost the same as a constant, but there are a few important and decisive differences:
It can change; although it is readonly, you can change it's value inside the static constructor of the declaring type. const can never change after initialized.
It is evaluated at runtime, not compile time as a true const.
Any type can be declared as a static readonly and initialized to any valid value as you would do with any regular field.
As a nittpicking side note, you shouldn't make G a constant ;). It changes, and quite a bit. G in Ecuador is different from G in the North Pole.
const variables are assigned values at time of definition.
They are available at compile time. You can even use a compile time evaluate-able expression at compile time. But once a value has been assigned to a const variable, it cannot be changed at any other time.
Using static field means the value will remain same for every user of the application, but this value can be changed by code in any of the classes, and it will change for every user of the application.
Do not use static for constants, use const only. const are by default static, and you cannot use static keyword with it.
Check this
void Main()
{
// You will not be able to change value for const variable.
Console.WriteLine(Myclass.G);
// You will be able to change value for static variable,
// and this change will impact all users of the application.
// For every user, this field will store value of 10 now.
// That will not be required or desired code behavior.
Myclass1.G = 10;
Console.WriteLine(Myclass1.G);
}
// Normal class with const field
class Myclass
{
public const double G=9.8;
}
//static class with static constructor
static class Myclass1
{
public static double G{get;set;}
static Myclass1()
{
G=9.8;
}
}
Read More
Here you are talking about two different things, and this is their definition from MSDN:
1- static modifier: To declare a static member, which belongs to the type itself rather than to a specific object. The static modifier can be used with classes, fields, methods, properties, operators, events, and constructors, but it cannot be used with indexers, finalizers, or types other than classes.
2- const keyword: To declare a constant field or a constant local. Constant fields and locals aren't variables and may not be modified. Constants can be numbers, Boolean values, strings, or a null reference. Don’t create a constant to represent information that you expect to change at any time.
So a static member is defined for a Class (for all its instances, and that's why you can access it directly from the name of the Class) but can be modified. a const field of class can not be modified.

Trying to understand static constructors

I am trying to understand need for static constructors. None of information I found answered following question I have. Why would you do this
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline;
// Static constructor is called at most one time, before any
// instance constructor is invoked or member is accessed.
static SimpleClass()
{
baseline = DateTime.Now.Ticks;
}
}
as opposed to this
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline = DateTime.Now.Ticks;
// Static constructor is called at most one time, before any
// instance constructor is invoked or member is accessed.
//static SimpleClass()
//{
//}
}
?
This is not dupe of other question, this is about static constructors which don't accept parameters.
The need is somehow obvious: You want to do more than some field initialization for your static members.
Logically if you have this class:
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline = DateTime.Now.Ticks;
}
You can re-write it to have the same effect:
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline;
static SimpleClass () {
baseline = DateTime.Now.Ticks;
}
}
But instead, you could do more in your static constructor such as inspecting (using reflection) some properties and emiting some fast accessors / getters to them, or just simple notify other systems that your type has been created, etc.
From Jeffrey Richter CLR via C# book:
When the C# compiler sees a class with static fields that use inline
initialization (the BeforeFieldInit class), the compiler emits the
class’s type definition table entry with the BeforeFieldInit metadata
flag. When the C# compiler sees a class with an explicit type
constructor (the Precise class), the compiler emits the class’s type
definition table entry without the BeforeFieldInit metadata flag. The
rationale behind this is as follows: initialization of static fields
needs to be done before the fields are accessed, whereas an explicit
type constructor can contain arbitrary code that can have observable
side effects; this code may need to run at a precise time.
Obviouselly there is something more than this happening behind the scenes, I would suggest you to read entire chapter from CLR via C#: "Type Constructors"
This is an example of a possible difference:
class SimpleClass
{
static readonly long A = DateTime.Now.Ticks;
static readonly long B = DateTime.Now.Ticks;
static SimpleClass()
{
}
}
A and B are not guaranteed to be the same value, though if you were to write it in the constructor, you could guarantee it:
class SimpleClass
{
static readonly long A;
static readonly long B;
static SimpleClass()
{
var ticks = DateTime.Now.Ticks;
A = ticks;
B = ticks;
}
}
In addition, order matters for instantiation of static members.
According to ECMA-334 regarding static field initialization:
The static field variable initializers of a class declaration
correspond to a sequence of assignments that are executed in the
textual order in which they appear in the class declaration. If a
static constructor (§17.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
So, we can write something like this:
class SimpleClass
{
public static readonly long A = IdentityHelper.GetNext();
public static readonly long B = IdentityHelper.GetNext();
static SimpleClass()
{
}
}
public static class IdentityHelper
{
public static int previousIdentity = 0;
public static int GetNext()
{
return ++previousIdentity;
}
}
Here, A is guaranteed to be assigned before B. In this example, A will be 1, and B will be 2. We can guarantee that A < B (assuming the identity does not overflow and there's no issues with threading). Now, if we re-order the fields:
public static readonly long B = IdentityHelper.GetNext();
public static readonly long A = IdentityHelper.GetNext();
The functionality changes. Thus, we've created a side-effect which is not immediately clear simply by re-ordering the fields definitions.
A more likely scenario is, we may want to do this:
class SimpleClass
{
public static readonly long A = IdentityHelper.GetExpensiveResult().A;
public static readonly long B = IdentityHelper.GetExpensiveResult().B;
static SimpleClass()
{
}
}
Here, we're unable to share GetExpensiveResult() between the fields.

C#: how to efficiently introduce "Immutable by default" to C#? Immutable attribute?

Reading F# and C# these days, one of the big difference is, F# variants are by default Immutable, most C# reference types are by default mutable.
This brings to a question, how to efficiently introduce this "Immutable as by default" to C# coding? er... i mean C# 4.0..
What came to my mind is an "Immutable Attribute".
So when this is docked to a class, by Aspect, each and every member of the class is checked, so that they are only mutable in constructors.
How do you think?
The readonly keyword is a language-level construct to perform the very action you're requesting. When applied to member variables, they can only be set in the constructor and must be set in the constructor.
I'm not familiar with F#, but C# does have a readonly keyword that can only be applied to members that are initialized at object creation:
public class MyExample
{
private readonly IDependency _dependency;
public MyExample(IDependency dependency)
{
_dependency = dependency;
}
public IDependency Dependency
{
get { return _dependency; }
}
}
The keyword can only be applied to members that are immutable, meaning there's no mechanism to alter them from outside the class.
I'm not entirely sure what you're trying to accomplish -- whether you're suggesting a new feature for C# or if you're asking how to implement forcing private variables to be immutable except during construction.
If it's the latter, you could accomplish that by making your private variables readonly when you declare them. You can't make every variable you declare "read only" by default, so you'll always have to specify this keyword, but with a bit of discipline when writing new code, it'd get the job done.
One more thing to note: a variable being immutable isn't the same as the object it points to being immutable.
For example,
public class MyClass
{
private readonly List<string> myList;
public MyClass()
{
myList = new List<string>(); // okay
}
public void DoStuff()
{
myList = new List<string>(); // not okay; myList is readonly!
myList.Add("this will work"); // okay -- the list itself is still mutable
}
}

How to make a variable (not class member) "read only" in C#

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.

Does C# resolve dependencies among static data members automatically?

If one static data member depends on another static data member, does C#/.NET guarantee the depended static member is initialized before the dependent member?
For example, we have one class like:
class Foo
{
public static string a = "abc";
public static string b = Foo.a + "def";
}
When Foo.b is accessed, is it always "abcdef" or can be "def"?
If this is not guaranteed, is there any better way to make sure depended member initialized first?
Like said before, static field initialization is deterministic and goes according to the textual declaration ordering.
Take this, for example:
class Foo
{
public static string b = a + "def";
public static string a = "abc";
}
Foo.b will always result in "def".
For that matter, when there is a dependency between static fields, it is better to use a static initializer :
class Foo
{
public static string b;
public static string a;
static Foo()
{
a = "abc";
b = a + "def";
}
}
That way, you explicitly express your concern about the initialization order; or dependency for that matter (even if the compiler won't help if you accidentally swap the initialization statements.) The above will have the expected values stored in a and b (respectively "abc" and "abcdef").
However, things might get twisty (and implementation specific) for the initialization of static fields defined in multiple classes. The section 10.4.5.1 Static field initialization of the language specification talks about it some more.
It will show allways "abcdef", because initialization goes top down in source, today just like before.
All static members will be initialized upon loading of the classtype holding them.

Categories

Resources