2011-10-19 3 views
4

私はC#でjabber.netを使用しています。私は混乱しているので、誰かがどのようにそれをやっているのか説明できます。 I私は入力する必要が部屋を保持するための読み取り専用JIDを作成しています、それはこの関数はどのように私のreadonly変数を変更しますか?

が誤解かもしれので、C++の背景から、まだC#にはかなり新しいです:

private readonly JID messagingRoomJID; 

public MyClass 
{ 
    // Reads from database but for purpose of this question 
    messagingRoomJID = new JID("[email protected]"); 
} 

後、私は参加したいです

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)); 

答えて

7

変数の値は変更されません。変数の値は単なる参考値です。その参考文献は以前と同じままです。

変更点は、参照が参照するオブジェクト内のデータです。 readonly修飾子のみが変数に適用されます。オブジェクト自体の変更可能性については何も言及していません。

参照とオブジェクトを区別することは非常に重要です。詳細はmy article on the topicを参照してください。

+0

すごい、たくさんの速い返答。私は今何が起こっているのか理解しています。私はそれがC++のconst参照にもっと似ていると思っていましたが、当然のことではありませんが、私は残念ですが、これがなぜそう多くの良い理由があると確信しています。それで、通常のインスタンスでオブジェクトを関数に渡すと、そのコードに影響されないという保証はありませんか? – Firedragon

+1

@Firedragon:あなたはオブジェクトを渡さない。値で参照を渡します(参照型で、ref/outパラメータではないと仮定します)。そして、可能であれば、オブジェクトが変更可能な場合は何でもオブジェクトを変更することができます。パラメータの受け渡しの詳細については、http://pobox.com/~skeet/csharp/parameters.htmlを参照してください。基本的に、C#がC++に似ていると想定しないでください - そうではありません! :) –

+0

それはそれのように聞こえるかもしれませんが、それは私が意味するもののようなものです。ちょうど自分自身を説明する上で最善ではない:私は参照が値によって渡されるので、それはC + +に似ていると思うが、同じconst正しさがないという点で異なる# – Firedragon

3

それはあなたのreadonly変数のプロパティを変更しているので:私はこれでそれを行うことができますが、私はそれが賢明であることを確認していないように見えます

se。例えば

、そう

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 
} 

、我々はコンストラクタで、それは一度を変更することができます。プロパティを含む複合型の場合は、フィールドなどを公開しているので、以降のものを変更できます。これは、readonly配列を持つ(一般的な例では)配列の要素を変更することができるため、一般的には悪い考えであり、少なくとも意図するものではないと考えられる理由です。

+0

実際には、インスタンスではなく読み取り専用のインスタンスへの参照であり、変数ではなく変数が参照している*インスタンス*のプロパティです。 – BoltClock

+0

は1つの回答のみ受け入れることができますが、あなたの偉大な返信には+1を返します – Firedragon

1

readonlyは、インスタンスへの参照が変更されないことを意味します。しかし、このオブジェクトの任意のフィールドを変更することができます。メソッドGetRoomに渡されると、参照渡しされます。したがって、GetRoomはオブジェクトのフィールドを変更できます。

2

したがって、私はJon Skeetの答えを正しいと考えます。 例として、クラス変数messagingRoomJIDは読み取り専用で参照用であるため、新しい値に割り当てることはできませんが、プロパティ "リソース"は読み取り専用ではないため、すべてのプロパティの値を変更できます。

GetRoom()メソッド呼び出しは、メモリ内のmessagingRoomJID変数参照を変更しません。許可されているプロパティの値の1つだけを変更します。

+0

これはJonの答えにコメントしている可能性があります! ! – V4Vendetta

+0

私は同意する、私はその時間のコメント特権を持っていなかった、私は今それを持っていると私の最初のコメントheres ..特権のための..! – VS1

0

MSDNによると、readonlyフィールドは、宣言中またはコンストラクタを使用して初期化できます。

readonlyフィールドは、宣言またはコンストラクタで初期化できます。したがって、readonlyフィールドは、使用されるコンストラクタに応じて異なる値を持つことができます。

しかし、あなたのコードのように、あなたは、初期化時またはコンストラクタを使用してのいずれか変更されていませんが、それでもプロパティResourceは値が含まれています。

Jon Skeetから指摘されているように、私はそれに追加しようとしましたが、参照型変数の値はnullまたはmemorry addressです。だから、

、あなたが宣言します。その時messagingRoomJID

private readonly JID messagingRoomJID; 

が読み取り専用であるが、いくつかのプロパティは、そのメモリ位置に存在している、この場合にはResourceは別の値に変更することができます。

関連する問題