Modify a const string via reflection/unsafe code?

W

wizofaus

Given the following code:

public class Test
{
static unsafe void StringManip(string data)
{
fixed (char* ps = data)
ps[0] = '$';
}

public const string Const = "Const";
public static readonly string ReadOnly = "ReadOnly";

static void Main(string[] args)
{
string value;

TypedReference tr = new TypedReference();
value = typeof(Test).GetField("Const").GetValueDirect(tr) as
string;
StringManip(value);
value = typeof(Test).GetField("ReadOnly").GetValueDirect(tr) as
string;
StringManip(value);

Console.WriteLine(Test.Const);
Console.WriteLine(Test.ReadOnly);

value = Test.Const;
StringManip(value);

Console.WriteLine(Test.Const);
}
}

I get the output

Const
$eadOnly
$onst

That is - a const string can only be manipulated with unsafe code
*directly*, and not via reflection, whereas a static readonly string
can be manipulated with unsafe code via reflection. Obviously none of
these practices would be normal or recommended, but if I did need to
modify a const string via reflection, I don't suppose there's any way
it might be possible? (I'm trying to do this to work my way around a
bug inside .NET).
 
C

Christof Nordiek

Hi,

the difference between a const and a readonly field is, that a read only
field is a storage location wich can only be written while class resp.
instance construction.
Constant values are evaluated while compilation and so, referencing methods
are using the value, wich was there while compile time. Still this doesn't
really declare, why the manipulation doesn't work, because they still
reference the same instance. Maybe GetValueDirect wirks differently with a
constant.

But even if this would work, this still wouldn't influence the logic of
other assemblies, and it surely doesn't influence occasions where the
constant is used inside a constant expression.

Why do you want to manipulate a const in the first place. If there is any
reason to change it, than it was an error for it, to be a constant.
A constant, aswell as a readonly field is there for a reason and many
method, maybe in other assemblies may reference it. You would influence all
this methods, causing a great mess. Even reparing a bug with this very
likely would produce new bugs on other places.

hth
Christof
 
G

Guest

The reason this does not work is because the value of a constant is taken at
compile time rather than a reference to the constant. This means that nowhere
in the code will actually reference the constants value apart from the
constant definition. This means the code after compilation is exactly the
same as:

public class Test
{
static unsafe void StringManip(string data)
{
fixed (char* ps = data)
ps[0] = '$';
}

public const string Const = "Const";
public static readonly string ReadOnly = "ReadOnly";

static void Main(string[] args)
{
string value;

TypedReference tr = new TypedReference();
value = typeof(Test).GetField("Const").GetValueDirect(tr) as
string;
StringManip(value);
value = typeof(Test).GetField("ReadOnly").GetValueDirect(tr) as
string;
StringManip(value);

Console.WriteLine("Const");
Console.WriteLine(Test.ReadOnly);

value = "Const";
StringManip(value);

Console.WriteLine("Const");
}
}



This doesnt actually give the output you specify but I imagine the last
Console.writeline in your code wrote out the variable value rather than the
const.

Remember that this happens because you told the compiler that the value of
the const field will never change and therefore it is more performant (at
runtime) to not reference the value but copy it around the compiled code

HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top