我在C#中使用jabber.net并且有一个让我困惑的怪癖,所以希望有人可以解释它是如何做到的。从C ++背景来看,我对C#还是很陌生,所以这可能是一个误解
我正在创建一个只读JID来保存我需要输入的房间:
private readonly JID messagingRoomJID;
public MyClass
{
// Reads from database but for purpose of this question
messagingRoomJID = new JID("user@myserver");
}
后来我想加入一个房间,这是我感到困惑的地方
conferenceManager = new ConferenceManager();
conferenceManager.Stream = xmppClient;
// Before entering this room messagingRoomJID.Resource == null
theRoom = conferenceManager.GetRoom(messagingRoomJID);
// But now messagingRoomJID.Resource contains my username
但资源如何改变?变量是只读的,但也不应该通过const引用传递,所以它是如何被更新的呢?
看起来我可以做到这一点,但我不确定这是明智的:
theRoom = conferenceManager.GetRoom(new JID(messagingRoomJID));
答案 0 :(得分:7)
它不会改变变量的值。变量的值只是一个引用。该参考文献与以前保持一致。
参考所引用的对象内的数据发生了变化。仅readonly
修饰符 适用于您的变量 - 它没有说明对象本身的可变性。
区分引用和对象非常重要 - 有关详细信息,请参阅my article on the topic。
答案 1 :(得分:3)
因为它正在更改readonly
变量的属性,而只有根元素本身是只读的。
例如,
private readonly int MyReadOnlyVariable;
private readonly ComplexType MyReadOnlyComplexType;
public MyClass()
{
MyReadOnlyVariable = 2; //valid
MyReadOnlyComplexType = something; //valid
}
public void NotAConstructor()
{
MyReadOnlyVariable = 2; //invalid
MyReadOnlyComplexType = somethingElse; //invalid
MyReadOnlyComplexType.Something = somethingElse; //valid
}
因此,我们可以在构造函数中更改 it 一次;但是在包含属性,暴露字段等的复杂类型的情况下,我们可以改变之后的那些。这就是为什么(对于一个常见的例子)具有readonly
数组通常是一个坏主意,或者至少可以想象它通常不是预期的 - 因为数组的元素可以改变。
答案 2 :(得分:2)
所以,我认为Jon Skeet的回答是正确的。 例如,您的类变量 messagingRoomJID 是readonly和引用,因此您无法将其分配给新值,但您当然可以更改其所有属性的值,因为属性“Resource”不是只读。
GetRoom()方法调用不会更改内存中的messagingRoomJID变量引用,它只会更改其允许的某个属性的值。
答案 3 :(得分:1)
readonly
表示不会更改对实例的引用。但是您可以更改此对象的任何字段。何时传递给方法GetRoom
,它通过引用传递。因此GetRoom
可以更改任何对象的字段。
答案 4 :(得分:0)
根据MSDN,只能在声明期间或使用构造函数初始化只读字段。
readonly字段可以在声明或构造函数中初始化。因此,readonly字段可以具有不同的值,具体取决于所使用的构造函数。
但是,在代码中,您在初始化期间或使用构造函数时不会更改,但属性Resource
仍然包含值。
正如Jon Skeet所指出的,我会尝试添加它,引用类型变量的值为null
或memorry address
。
所以,当你声明:
private readonly JID messagingRoomJID;
此时messagingRoomJID
是只读的,但该内存位置的属性很少,在这种情况下Resource
可以更改为其他值。