Immutable local 'variables' in C# - c#

I'm new to C# (C++ programmer mainly, with Java as a strong second, and some others I use less often); I'm using C# with Unity, but I have a question that seems to be C# related rather than Unity.
I've been moving somewhat towards functional-style programming, i.e. instead of
// C++
int someFunction(int a) {
int someCalculatedValue = a * a;
someCalculatedValue /= 2;
return someCalculatedValue * 3;
}
I'd do something like this
// Again C++
int someFunction(int a) {
const int inputSquared = a * a;
const int inputSquaredHalved = inputSquared / 2;
return inputSquaredHalved * 3;
}
Now, I'd like to do that in C#, but I've tried this
// C#
const float maxGrowth = GrowthRate * Time.deltaTime;
But Mono complains, saying maxGrowth isn't being assigned a 'constant value' - so I'm assuming C#'s const keyword is actually equivalent to 'constexpr' from C++11?
If so, is there a way of doing what I want in C#? Preferably without invoking some container class (unless the compiler is good at making that efficient?).
I assume from what I've read C# is much closer to Java overall than C++ in language; immutable classes rather than const-member functions?

You can declare your local variable as an iteration variable. Iteration variables are readonly.
Yes, it is ugly.
foreach (float maxGrowth in new[] { GrowthRate * Time.deltaTime })
{
maxGrowth = 0; // won't compile: "error CS1656: Cannot assign to 'maxGrowth' because it is a 'foreach iteration variable'"
}

There is no equivalent for local variables: Declare it as a field.
readonly
When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.

I believe that a better way for this case is using statement
Sample:
using (var font = new Font("Arial", 10.0f))
{
byte charset = font.GdiCharSet;
}
font variable is immutable
Reference:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement

Related

Is it possible to do fast unchecked cast of structs in C#?

Suppose you have two structs that have exactly the same memory layout. Is it possible to do a very fast unchecked memory cast from one to the other in C#/.NET?
//my code base
[StructLayout(LayoutKind.Sequential)]
public struct VectorA
{
float x;
float y;
float z;
}
//defined by a third party library
[StructLayout(LayoutKind.Sequential)]
public struct VectorB
{
float a;
float b;
float c;
}
//somewhere else in my code
var vectorA = new VectorA();
//then calling a method from the library
MethodFromThirdPartyLibrary((VectorB)vectorA); //compiler error
Of course it should be faster as a method that assigns the data fields and creates a new copy in memory.
Also: The 3d vector is only an example, same problem for matrices which is 16 floats and Vector2, Vector4, ...
EDIT: Improved code with more comments and better usage example.
Why would it be faster? Would it be faster in C++ than writing the copy explicitly as in C#? Remember, you only have 3 x 32-bit numbers you want to copy from one place to another, so it's not exactly a good fit for vectorization.
It's likely if you had an array of these structures that you could get some speed up using vectorized load/stores in an unrolled loop in assembler. But you've not stated that in the question.
The main overhead here is probably the method call, rather than the assignment:
static void VecAToB(ref VectorA vectorA, ref VectorB vectorB)
{
vectorB.x = vectorA.a;
vectorB.y = vectorA.b;
vectorB.z = vectorA.c;
}
You might like to try:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void VecAToB(ref VectorA vectorA, ref VectorB vectorB)
{
vectorB.x = vectorA.a;
vectorB.y = vectorA.b;
vectorB.z = vectorA.c;
}

What is the ampersand character at the end of an object type?

I had to de-compile some code and I don't know what this syntax is? Can y'all help, or point me to a write-up about what it is? I've Googled and searched this site and can't find anything.
Just one line of code:
Rectangle pageBounds;
// ISSUE: explicit reference operation
// ISSUE: variable of a reference type
Rectangle& local = #pageBounds;
What is the # symbol at the end of the Rectangle object type, and the # before the pageBounds variable?
This is my last line of code that I need to fix in order to get this executable to compile again.
Here's the method that uses this syntax, can I get away with removing it?
protected override void OnPrintPage(PrintPageEventArgs e)
{
Application.DoEvents();
++this._pageNum;
float num1;
if (this.Header != null)
{
num1 = this.Header.CalculateHeight(this, e.Graphics);
this.Header.Draw(this, (float) e.MarginBounds.Top, e.Graphics, e.MarginBounds);
}
else
num1 = 0.0f;
float num2;
if (this.Footer != null)
{
num2 = this.Footer.CalculateHeight(this, e.Graphics);
this.Footer.Draw(this, (float) e.MarginBounds.Bottom - num2, e.Graphics, e.MarginBounds);
}
else
num2 = 0.0f;
Rectangle pageBounds;
// ISSUE: explicit reference operation
// ISSUE: variable of a reference type
Rectangle& local = #pageBounds;
int left = e.MarginBounds.Left;
Rectangle marginBounds = e.MarginBounds;
int y = (int) ((double) marginBounds.Top + (double) num1);
marginBounds = e.MarginBounds;
int width = marginBounds.Width;
marginBounds = e.MarginBounds;
int height = (int) ((double) marginBounds.Height - (double) num2 - (double) num1);
// ISSUE: explicit reference operation
local = new Rectangle(left, y, width, height);
float yPos = (float) pageBounds.Top;
bool flag = false;
int num3 = 0;
while (this._printIndex < this._printElements.Count)
{
PrintElement printElement = (PrintElement) this._printElements[this._printIndex];
float num4 = printElement.CalculateHeight(this, e.Graphics);
if ((double) yPos + (double) num4 > (double) pageBounds.Bottom && num3 != 0)
{
flag = true;
break;
}
else
{
printElement.Draw(this, yPos, e.Graphics, pageBounds);
yPos += num4;
++this._printIndex;
++num3;
}
}
e.HasMorePages = flag;
}
The comments right before that line of code are telling you exactly what's going on. The & after a type name indicates that it's a reference type, and the # before a variable name generates a reference to that variable.
(The # sign can also be used in C# code to escape keywords for use as variable names but that's not what is happening here. pageBounds is not a C# keyword.)
Note that this is not valid C# syntax -- you cannot take a reference to a local variable in C#, although the CLR supports it. (NOTE: As of C# 7.0, this is no longer true; the syntax is described here, but it does not use the & so this decompiled code is still invalid C#).
Creating a reference to a local variable happens implicitly when you use ref and out parameters, for example, but the keywords are used instead of explicitly typing the parameters as reference. (e.g. if you had an out int x, internally that variable is of type Int32&.) The intent of the code, if it were legal C#, would be that pageBounds and local were the same instance with two different names; anything you do to one happens to the other. So, for example, this illegal code:
Rectangle pageBounds;
Rectangle& local = #pageBounds;
local = new Rectangle();
would be the same as this legal code:
Rectangle pageBounds = new Rectangle();
If you tried to compile the code as-decompiled, you would get an error because the compiler treats & as the bitwise and operator, and will complain that you used a type as if it were a variable. But that's ok because you didn't get it from a C# source file. You decompiled an IL method to get it, and there are a lot of things you can do in IL that are illegal in C#. This happens all the time when you decompile code; you see illegal class and method names for example. It just means that the compiler generated IL based on the original code that does not translate directly back into C#, but behaves the way you wanted. The code you are getting back is simply the decompiler's best attempt to produce C# code from the IL it has.
You can see examples of the sort of code that produces these references in the numerous Jetbrains bug reports about them:
http://youtrack.jetbrains.com/issue/DOTP-521
http://youtrack.jetbrains.com/issue/DOTP-1077
http://youtrack.jetbrains.com/issue/DOTP-524
See Here - http://msdn.microsoft.com/en-us/library/aa664670(v=vs.71).aspx (Have never used though)
The prefix "#" enables the use of keywords as identifiers, which is useful when interfacing with other programming languages. The character # is not actually part of the identifier, so the identifier might be seen in other languages as a normal identifier, without the prefix. An identifier with an # prefix is called a verbatim identifier. Use of the # prefix for identifiers that are not keywords is permitted, but strongly discouraged as a matter of style.
The example:
class #class
{
public static void #static(bool #bool) {
if (#bool)
System.Console.WriteLine("true");
else
System.Console.WriteLine("false");
}
}
class Class1
{
static void M() {
cl\u0061ss.st\u0061tic(true);
}
}

C# reference assignment operator?

for example:
int x = 1;
int y = x;
y = 3;
Debug.WriteLine(x.ToString());
Is it any reference operator instead of "=" on line:3,
to make the x equal to 3 , if i assign y =3 .
I once wrote a prototype of a version of C# that had that feature; you could say:
int x = 123;
ref int y = ref x;
and now x and y would be aliases for the same variable.
We decided to not add the feature to the language; if you have a really awesome usage case I'd love to hear it.
You're not the first person to ask about this feature; see Can I use a reference inside a C# function like C++? for more details.
UPDATE: The feature will likely be in C# 7.
'int' is a value type and so copies the value on assignment, as you have discovered.
You could use pointers in the traditional C/C++ sense by using an 'unsafe' block but then the pointers are only usable inside that block which limits its use. If instead you want to access the value outside of an 'unsafe' block then you need to convert to using a reference instead.
Something like this...
var x = new Tuple<int>(1);
var y = x;
y.Item1 = 3;
This is not exactly what you're asking, but I thought it might be helpful. If you want a pointer alias inside a function, you can use the ref keyword like such:
public static void RefExample(ref int y)
{
y = 3;
}
main()
{
int x = 5;
RefExample(ref x);
Console.WriteLine(x); // prints 3
}
You can use pointers like in C
int x = 1;
unsafe
{
int* y = &x;
*y = 3;
}
Debug.WriteLine(x.ToString());
(Note you have to compile with the unsafe flag)
The only way to do this is to use "unsafe" code, and actually use pointers. Pointers cannot exist outside of unsafe code blocks in C#. You should then be able to use pointers the same way you do in C/C++
Check out this page for how to use "unsafe" code blocks.
I wanted to comment Eric Lippert's answer, but new users cannot comments posts. So, I think I have such usage.
Take a look at this code:
private void SetGridColumns(ref RegistryKey targetKey, List<ColInfo> cols)
{
string targetKeyName = Path.GetFileName(targetKey.Name);
m_grids.DeleteSubKeyTree(targetKeyName, false);
targetKey.Close();
targetKey = m_grids.CreateSubKey(targetKeyName);
//...
}
public void SetColumns(List<ColInfo> cols, bool youth)
{
RegistryKey key = youth ? m_youthGrid : m_mainGrid;
SetGridColumns(ref key, cols);
}
It should work like that:
In SetColumns I call SetGridColumns with key depending on "youth" param. I would like my key to be first deleted and then recreated. m_mainGrid is of course member of a class.
In this case, key is indeed deleted and recreated. But recreated is only "targetKey" in SetGridColumns, not my m_mainGrid.
So, the only thing I can do here is to make usage of pointers which is not preferred way in C#.
If I could only do:
ref RegistryKey key = youth ? m_youthGrid : m_mainGrid;
everything should work fine.

Can parameters be constant?

I'm looking for the C# equivalent of Java's final. Does it exist?
Does C# have anything like the following:
public Foo(final int bar);
In the above example, bar is a read only variable and cannot be changed by Foo(). Is there any way to do this in C#?
For instance, maybe I have a long method that will be working with x, y, and z coordinates of some object (ints). I want to be absolutely certain that the function doesn't alter these values in any way, thereby corrupting the data. Thus, I would like to declare them readonly.
public Foo(int x, int y, int z) {
// do stuff
x++; // oops. This corrupts the data. Can this be caught at compile time?
// do more stuff, assuming x is still the original value.
}
Unfortunately you cannot do this in C#.
The const keyword can only be used for local variables and fields.
The readonly keyword can only be used on fields.
NOTE: The Java language also supports having final parameters to a method. This functionality is non-existent in C#.
from http://www.25hoursaday.com/CsharpVsJava.html
EDIT (2019/08/13):
I'm throwing this in for visibility since this is accepted and highest on the list. It's now kind of possible with in parameters. See the answer below this one for details.
This is now possible in C# version 7.2:
You can use the in keyword in the method signature. MSDN documentation.
The in keyword should be added before specifying a method's argument.
Example, a valid method in C# 7.2:
public long Add(in long x, in long y)
{
return x + y;
}
While the following is not allowed:
public long Add(in long x, in long y)
{
x = 10; // It is not allowed to modify an in-argument.
return x + y;
}
Following error will be shown when trying to modify either x or y since they are marked with in:
Cannot assign to variable 'in long' because it is a readonly variable
Marking an argument with in means:
This method does not modify the value of the argument used as this parameter.
The answer: C# doesn't have the const functionality like C++.
I agree with Bennett Dill.
The const keyword is very useful. In the example, you used an int and people don't get your point. But, why if you parameter is an user huge and complex object that can't be changed inside that function? That's the use of const keyword: parameter can't change inside that method because [whatever reason here] that doesn't matters for that method. Const keyword is very powerful and I really miss it in C#.
Here's a short and sweet answer that will probably get a lot of down votes. I haven't read all of the posts and comments, so please forgive me if this has been previously suggested.
Why not take your parameters and pass them into an object that exposes them as immutable and then use that object in your method?
I realize this is probably a very obvious work around that has already been considered and the OP is trying to avoid doing this by asking this question, but I felt it should be here none-the-less...
Good luck :-)
I'll start with the int portion. int is a value type, and in .Net that means you really are dealing with a copy. It's a really weird design constraint to tell a method "You can have a copy of this value. It's your copy, not mine; I'll never see it again. But you can't change the copy." It's implicit in the method call that copying this value is okay, otherwise we couldn't have safely called the method. If the method needs the original, leave it to the implementer to make a copy to save it. Either give the method the value or do not give the method the value. Don't go all wishy-washy in between.
Let's move on to reference types. Now it gets a little confusing. Do you mean a constant reference, where the reference itself cannot be changed, or a completely locked, unchangeable object? If the former, references in .Net by default are passed by value. That is, you get a copy of the reference. So we have essentially the same situation as for value types. If the implementor will need the original reference they can keep it themselves.
That just leaves us with constant (locked/immutable) object. This might seem okay from a runtime perspective, but how is the compiler to enforce it? Since properties and methods can all have side effects, you'd essentially be limited to read-only field access. Such an object isn't likely to be very interesting.
Create an interface for your class that has only readonly property accessors. Then have your parameter be of that interface rather than the class itself. Example:
public interface IExample
{
int ReadonlyValue { get; }
}
public class Example : IExample
{
public int Value { get; set; }
public int ReadonlyValue { get { return this.Value; } }
}
public void Foo(IExample example)
{
// Now only has access to the get accessors for the properties
}
For structs, create a generic const wrapper.
public struct Const<T>
{
public T Value { get; private set; }
public Const(T value)
{
this.Value = value;
}
}
public Foo(Const<float> X, Const<float> Y, Const<float> Z)
{
// Can only read these values
}
Its worth noting though, that its strange that you want to do what you're asking to do regarding structs, as the writer of the method you should expect to know whats going on in that method. It won't affect the values passed in to modify them within the method, so your only concern is making sure you behave yourself in the method you're writing. There comes a point where vigilance and clean code are the key, over enforcing const and other such rules.
I know this might be little late.
But for people that are still searching other ways for this, there might be another way around this limitation of C# standard.
We could write wrapper class ReadOnly<T> where T : struct.
With implicit conversion to base type T.
But only explicit conversion to wrapper<T> class.
Which will enforce compiler errors if developer tries implicit set to value of ReadOnly<T> type.
As I will demonstrate two possible uses below.
USAGE 1 required caller definition to change. This usage will have only use in testing for correctness of your "TestCalled" functions code. While on release level/builds you shouldn't use it. Since in large scale mathematical operations might overkill in conversions, and make your code slow. I wouldn't use it, but for demonstration purpose only I have posted it.
USAGE 2 which I would suggest, has Debug vs Release use demonstrated in TestCalled2 function. Also there would be no conversion in TestCaller function when using this approach, but it requires a little more of coding of TestCaller2 definitions using compiler conditioning. You can notice compiler errors in debug configuration, while on release configuration all code in TestCalled2 function will compile successfully.
using System;
using System.Collections.Generic;
public class ReadOnly<VT>
where VT : struct
{
private VT value;
public ReadOnly(VT value)
{
this.value = value;
}
public static implicit operator VT(ReadOnly<VT> rvalue)
{
return rvalue.value;
}
public static explicit operator ReadOnly<VT>(VT rvalue)
{
return new ReadOnly<VT>(rvalue);
}
}
public static class TestFunctionArguments
{
static void TestCall()
{
long a = 0;
// CALL USAGE 1.
// explicite cast must exist in call to this function
// and clearly states it will be readonly inside TestCalled function.
TestCalled(a); // invalid call, we must explicit cast to ReadOnly<T>
TestCalled((ReadOnly<long>)a); // explicit cast to ReadOnly<T>
// CALL USAGE 2.
// Debug vs Release call has no difference - no compiler errors
TestCalled2(a);
}
// ARG USAGE 1.
static void TestCalled(ReadOnly<long> a)
{
// invalid operations, compiler errors
a = 10L;
a += 2L;
a -= 2L;
a *= 2L;
a /= 2L;
a++;
a--;
// valid operations
long l;
l = a + 2;
l = a - 2;
l = a * 2;
l = a / 2;
l = a ^ 2;
l = a | 2;
l = a & 2;
l = a << 2;
l = a >> 2;
l = ~a;
}
// ARG USAGE 2.
#if DEBUG
static void TestCalled2(long a2_writable)
{
ReadOnly<long> a = new ReadOnly<long>(a2_writable);
#else
static void TestCalled2(long a)
{
#endif
// invalid operations
// compiler will have errors in debug configuration
// compiler will compile in release
a = 10L;
a += 2L;
a -= 2L;
a *= 2L;
a /= 2L;
a++;
a--;
// valid operations
// compiler will compile in both, debug and release configurations
long l;
l = a + 2;
l = a - 2;
l = a * 2;
l = a / 2;
l = a ^ 2;
l = a | 2;
l = a & 2;
l = a << 2;
l = a >> 2;
l = ~a;
}
}
If you often run into trouble like this then you should consider "apps hungarian". The good kind, as opposed to the bad kind. While this doesn't normally tries to express constant-ness of a method parameter (that's just too unusual), there is certainly nothing that stops you from tacking an extra "c" before the identifier name.
To all those aching to slam the downvote button now, please read the opinions of these luminaries on the topic:
Eric Lippert
Larry Osterman
Joel Spolsky
If struct is passed into a method, unless it's passed by ref, it will not be changed by the method it's passed into. So in that sense, yes.
Can you create a parameter whose value can't be assigned within the method or whose properties cannot be set while within the method? No. You cannot prevent the value from being assigned within the method, but you can prevent it's properties from being set by creating an immutable type.
The question isn't whether the parameter or it's properties can be assigned to within the method. The question is what it will be when the method exits.
The only time any outside data is going to be altered is if you pass a class in and change one of it's properties, or if you pass a value by using the ref keyword. The situation you've outlined does neither.
The recommended (well, by me) is to use an interface that provides read only access to the members. Remembering that if the "real" member is a reference type, then only provide access to an interface supporting read operations for that type -- recursing down the entire object hierarchy.

How to declare a local constant in C#?

How to declare a local constant in C# ?
Like in Java, you can do the following :
public void f(){
final int n = getNum(); // n declared constant
}
How to do the same in C# ? I tried with readonly and const but none seems to work.
Any help would be greatly appreciated.
Thanks.
In C#, you cannot create a constant that is retrieved from a method.
Edit: dead link
http://msdn.microsoft.com/en-us/library/e6w8fe1b(VS.71).aspx
This doc should help:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
A constant expression is an expression that can be fully evaluated at
compile time.
Declare your local variable as an iteration variable. Iteration variables are readonly
(You didn't ask for a pretty solution).
public void f()
{
foreach (int n in new int[] { getNum() }) // n declared constant
{
n = 3; // won't compile: "error CS1656: Cannot assign to 'n' because it is a 'foreach iteration variable'"
}
}
I'm not sure why readonly and const didn't work for you since these are the keywords you need. You use const if you have a literal (except for array literals) and readonly otherwise:
public void f()
{
const int answer = 42;
}
private readonly int[] array = new int[] { 1, 2, 3, 4 };
private readonly DateTime date = DateTime.Now;
public void g()
{
Console.WriteLine(date.ToString());
}
readonly only works on class level (that is, you can only apply it to fields). Also as a consequence of const requiring a literal, it's inherently static while a readonly field can be either static or instance.
As of 2018-10-02, it isn't possible to have a readonly local in c#, but there is an open proposal for that feature that has ongoing discussion.
This article provides a useful summary.
There is a sort of workaround that requires ReSharper. You can't get readonly locals, but you can at least detect mutated ones and color them differently.
Use the Fonts and Colors item Resharper Mutable Local Variable Identifier.
For me, I have locals colored grey, and then I chose a bold white for the mutated variables (this is with a dark theme). This means that any variable that is written to more than once shows up bright compared to regular ones. You can then do what you can to try to avoid having a mutated variable, or if the method really does require one then it will at least be highlighted.
In the example you gave, you need to declare the variable as static, because you're initializing it with a method call. If you were initializing with a constant value, like 42, you can use const. For classes, structs and arrays, readonly should work.
The const keyword is used to modify a
declaration of a field or local
variable.
From MSDN.
Since C# can't enforce "const correctnes" (like c++) anyway, I don't think it's very useful. Since functions are very narrwoly scoped, it is easy not to lose oversight.

Categories