如果一个对象是readonly或const,是否可以转换该对象使其可写? 类似于C ++ const_cast的东西。
答案 0 :(得分:12)
在C#中不可能,就像它在C ++中不可能一样。在C ++中,如果对象实际上是const,那么你不能const_cast
将constness带走并写入它而不调用未定义的行为:
struct foo { const int x; };
foo a;
int& b = const_cast<int&>(a.x);
b = 17; // invokes undefined behaviour
C#中的readonly
字段仅表示无法重新分配字段本身。它类似于C ++中的T *const
或T&
。您可以通过其成员随意更改引用的对象。
class Foo { public int x; }
class Bar { public readonly Foo y = new Foo(); }
Bar a = new Bar();
a.y.x = 3; // valid
a.y = new Foo(); // invalid
嗯,我不是在说实话。您可以通过反射 1 :来欺骗和更改readonly
字段
typeof(string).GetField("Empty").SetValue(null, "bar");
// this effectively makes string.Empty equal to "bar", with disastrous consequences
// It requires full trust though.
// Obviously, it's evil.
如果它是const
字段,那么即使这个技巧也行不通。
const
字段在使用它们的程序集中硬编码,而不是保留对原始程序集的引用:
// Assembly A.dll
public class Foo { public static const int X = 42; }
// Assembly B.dll
int y = Foo.X;
// this is the equivalent to:
int y = 42;
这意味着如果您重新编译A.dll并将Foo.X
的值更改为23,那么B.dll在重新编译之前仍会使用42。
所有这一切,如果你想要一个你想要改变的领域,就不要让它成为readonly
。如果你希望它是由类可变的,但是从外部是不可变的,那么将它设为private并添加一个只读属性(注意:这与readonly
字段不同):
class Foo
{
private int bar;
public int Bar
{
get { return bar; }
}
}
1 这个is not really guaranteed,但它适用于Microsoft实现。如果你想知道为什么这个hack可以工作,你可以阅读Eric Lippert's explanation。请务必阅读有关readonly
on value types的答案。不言而喻,不要在家里做这个。
答案 1 :(得分:1)
您将无法修改const
本身的值。您所能做的就是复制并更改该副本。除非我误解了这个问题......?
请记住,在C#const
中,无论如何都是一个非常有限的关键字,你只能在const
声明某些内容,并且只能在编译时:
http://msdn.microsoft.com/en-us/library/e6w8fe1b(v=VS.100).aspx
不确定为什么要改变常量。
答案 2 :(得分:1)
没有。参考或值将是只读的。
但是,您可以修改引用的属性,也可以只复制一个值。
答案 3 :(得分:0)
对象不是readonly或const,只有变量。这意味着您只能为这样的变量赋值一次(在const
的情况下)或仅在构造所有者对象之前(在readonly
的情况下)。
分配给readonly
变量的对象仍然可以更改,除非它是不可变的(如string
)。
答案 4 :(得分:0)
您可以在 CSharp readonly
中强制转换(与 C++ const
等效)。 CSharp const
可以用 constexpr
翻译成 C++,不能丢弃。
为此,您可以调用 Unsafe.AsRef
- 其含义与 C++ const_cast
相同:
using System;
class App{
static readonly int i = 42;
static void Main(){
Console.WriteLine(i);
System.Runtime.CompilerServices.Unsafe.AsRef(i) = 777;
Console.WriteLine(i);
}
}
在 C++ 中看起来是一样的:
#include <iostream>
class App{
public:
static inline int iStorage= 42;
static inline const int& i = iStorage;
static void Main(){
std::cout << i << '\n';
*const_cast<int*>(&i) = 777;
std::cout << i <<'\n';
}
};
int main(){
App::Main();
}
仅在 static const
的情况下,C++ 实现允许将数据存储在只读内存中(标准明确允许)。
这通常用于像 int
这样的简单类型 - 原因是没有 constexpr 但希望具有相同的行为 - 因此 static const
有时与 constexpr
具有相同的含义。