题
如何确定 C# 中的类是否不可变?
解决方案
有是ImmutableObjectAttribute
,但这是很少使用和管理不善的支持 - 当然不是强制的(你可以标记与[ImmutableObject(true)]
可变对象AFAIK,这这影响的唯一的事情是IDE处理属性的方式(即以示/不显示命名属性选项)。
在现实中,你必须检查FieldInfo.IsInitOnly
,但这只适用于真正的100%稳定的类型(假设没有反射的滥用等);它不与冰棍不变性帮助,也没有东西,是在实践中不可变的,而不是在其执行;即它们不能被制成为公开可变的,但在理论上该对象支持它。
这里一个典型的例子是串......每个人都“知道” string
是不可改变的......当然,StringBuilder
确实变异发动机罩下的字符串。不,认真...
它是如此很难定义不变性给定此,更不用说鲁棒检测它...
其他提示
您不能,你只能猜测。 如果所有字段是只读的,一旦构造完成的实例将是不可改变的。 这一点很重要,如果你有以下它会出现可变的实例吧。
class Foo
{
public readonly int X
public readonly int Y
public Foo(int x, int y, Bar bar)
{
this.X = x;
bar.ShowYourself(this);
this.Y = y;
bar.ShowYourself(this);
}
}
但是,如果在所谓一成不变的类中的字段是一个集合(只有不读)然后调用类的不可变的很可能是不正确的(因为它的状态可以改变)
请注意,即使所有字段都是只读反射被允许修改的字段。
检查上性能没有设置器将是一个非常差的启发式确实
部分问题在于“不可变”可以有多种含义。以 ReadOnlyCollection<T> 为例。
我们倾向于认为它是不可变的。但是如果它是 ReadOnlyCollection<SomethingChangeable> 该怎么办?另外,由于它实际上只是我传递给构造函数的 IList 的包装器,如果我更改原始 IList 会怎样?
一个好的方法可能是创建一个名称如 ReadOnlyAttribute 的属性,并用它标记您认为只读的类。对于您无法控制的类,您还可以维护您认为不可变的已知类型的列表。
编辑:有关不同类型不变性的一些很好的示例,请阅读 Eric Lippert 的这一系列帖子: http://blogs.msdn.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx
据我所知,除非它明确记载,也没有办法确定一个类是否是不可变的或者不C#。
可以,但是,使用反射来检查对性质塞特斯的存在;然而,缺乏制定者并不保证不可改变内部状态可以改变这些属性的值是否可以明确地设置与否。
此外,检查了“IsInitOnly”标志的所有类的领域,再次使用反射,可能表明不变性,但它并不能保证它。
编辑:这里有一个类似的问题,就问Java语言,其答案也适用于这里。
通过代码,我不知道,但据我所知,如果你看看另一个不可变类型的IL,如字符串你会的不可以看到newobj
IL指令(你会看到ldstr字符串),也许是检查创建的IL可以告诉一个办法,只是猜测...
您从运行时获得的唯一帮助是,如果在类中的所有字段为“只读”注释。 [编辑,见@ShuggyCoUk]甚则CLR将让你写了它。我只是验证它。啊。
可以得到从经由反射类的字段信息的对象,并检查IsInitOnly。