It is often recommended to use immutable structs in .NET programming, since using mutable structs sets one up for simple mistakes. However, when I attempt to assign a new value by instantiating a new struct, I get error C3892 in C++ yet the equivalent code in C# has no issue. This is a problem because this prevents me from initializing an array of immutable structs.
The issue is easily worked around by using a readonly property instead of a field, but I would like to know why I cannot do the same thing in C++/CLI as in C#. Am I doing something wrong, or is this simply a limitation (or bug) in C++/CLI? Is there any way to make use of arrays of immutable structs in C++/CLI or must I avoid them?
C++ Header (named "AnnoyingCppBug.h"):
using namespace System;
namespace AnnoyingCppBug {
public value struct immutableType
{
const int Value;
immutableType(int value)
: Value(value) {}
};
public value struct immutableWorkaround
{
property int Value
{
int get() { return _value; }
}
immutableWorkaround(int value)
: _value(value) {}
private:
int _value;
};
public value struct mutableType
{
int Value;
mutableType(int value)
: Value(value) {}
};
public value struct Class1 abstract sealed
{
static void Test();
};
}
C++ Source File:
#include "stdafx.h"
#include "AnnoyingCppBug.h"
namespace AnnoyingCppBug {
void Class1::Test()
{
auto imm1 = immutableType(0);
auto imm2 = immutableWorkaround(0);
auto imm3 = mutableType(0);
imm1 = immutableType(1); // error C3892: 'arr1': you cannot assign to a variable that is const
imm2 = immutableWorkaround(1);
imm3 = mutableType(1);
// The reason this matters is because I need to initialize an array:
auto arr = gcnew array<immutableType>(1);
arr[0] = immutableType(0); // error C3892: 'arr1': you cannot assign to a variable that is const
}
}
C# Code that does the same but builds fine:
struct immutableType
{
public readonly int Value;
public immutableType(int value)
{
Value = value;
}
}
static void Test()
{
var imm = new immutableType(0);
imm = new immutableType(1);
var arr = new immutableType[1];
arr[0] = new immutableType(1);
}
The answer was provided by Hans Passant in the comments on the question: I mistakenly used the C++ only (not C++/CLI) keyword const as if it meant the same as C# keyword readonly. The correct keyword that will be compiled into CLR equivalently to the C# keyword readonly is "initonly".
The const keyword will only instruct the compiler to generate errors but not ever produce any different CLR byte code. In general, given this revelation, I would recommend not to ever use the const keyword in managed C++ code. I also think that the C++/CLI compiler should generate a warning, but perhaps there are good reasons it does not (after all the compiler isn't meant to be a teacher).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With