2010-11-30 15 views
1

メソッドに文字列変数を渡しています。私は文字列が参照型であることを知っていますが、メソッド内で割り当てる値は失われます。メソッド内の参照型(文字列)を変更する

public static void TestMethod(string myString) 
{ 
    myString = "world"; 
} 

static void Main(string[] args) 
{ 
    string s = "hello"; 
    Console.WriteLine(s); // output is "hello" 
    TestMethod(s); 
    Console.WriteLine(s); // output is also "hello" not "world" !? 
} 

とにかく、これは配列などでは起こりません。誰かが理由を説明することはできますか?

+0

の可能重複(HTTP [値渡し間で異なるとC#を使用して参照することによって通過しているもの]:あなたは方法で変更できるようにあなたは、変数を渡すrefキーワードを使用

。 //stackoverflow.com/questions/1293111/what-is-different-between-passing-by-value-and-passing-by-reference-using-c) – LBushkin

+0

修正された文字列をTestMethodに返すことはできませんか? –

答えて

6

myString = "world"は新しい文字列をパラメータに割り当て、既存の文字列を更新しないためです。元の参照を文字列に更新するには、パラメータをrefで渡す必要があります。

public static void TestMethod(ref string myString) 
{ 
    myString = "world"; 
} 

static void Main(string[] args) 
{ 
    string s = "hello"; 
    Console.WriteLine(s); // output is "hello" 
    TestMethod(ref s); 
    Console.WriteLine(s); // output is also "hello" not "world" !? 
} 
1

これを行うには、メソッドのシグネチャのパラメータに "ref"キーワードを追加する必要があります。

あなたの文字列は参照渡しされますが、メソッドに渡すときにはMain()とTestMethod()の2つの参照があります。 TestMethod()の変数に新しい値を代入すると、その参照は変更されますが、Main()の変数は参照されません。

再割り当ての代わりにTestMethod()から文字列を変更できるのであれば、Main()ではエフェクトが表示されますが、不変なので文字列ではできません。

これをさらに試してみると、TestMethod()を変更してIListを受け取り、このリストに項目を追加することができます。これらの新しい項目はMain()から渡された変数で確認できます。 TestMethod(IList listArg)を変更してlistArgを新しいリスト(listArg = new List)に最初に再割り当てしてから項目を追加すると、Main()のリストは変更されません。これは同じ考えです。

1

はい、ref(またはout)がなければ、新しいオブジェクトをパラメータに割り当てることができないためです。 refを渡さなかったので、メソッドの外側の変数は変更されなかった元の文字列を参照します。その結果、文字列は不変であるため、インスタンス化されると新しい文字列を作成せずに何もできません。

配列内の参照が不変ではないため、配列を変更することができます(配列の内容を変更することができます)。my_object 1を「BLAH」に置き換えると言うことができます。メソッド外の配列への参照は変更されていないため、配列内の値を置換して配列の外部にアクセスすることができます。

Link to String in MSDN (talks about immutability)

+0

これは文字列が不変であるという事実とは直接関係しません。 – SpeksETC

+0

そうでない場合は、不変ではないオブジェクトの内部プロパティを変更して、それらが外部に表示されるようにすることができますこのメソッドは、文字列が変更可能な場合、技術的には値を変更して呼び出しメソッドに表示させることができます。文字列の代わりにStringBuilderオブジェクトを渡すことを考えてください。あなたは全く新しいStringBuilderをそのパラメータに再割り当てすることはできません。 – kemiller2002

+0

私は完全に同意します。最初の行があるコードサンプルから言えば:myString = "world" - 同じことがどんなタイプのmyStringでも起こります内部プロパティが変更されていないので、変数自体が別のインスタンスに割り当てられています。 – SpeksETC

0

文字列は、あなたが、アレイ内の項目をどうのように、それは、値だ変更できないことを意味し、不変です。文字列オブジェクトは、異なる文字列オブジェクトで置き換えることができます。

配列オブジェクトを置き換えると同じことが起こります。これは、パラメータ変数に新しい配列を配置しますが、それはあなたがメソッドを呼び出すために使用される変数は変更されませんので、あなたが渡された配列を置き換えるものではありません:

public static void TestMethod(string[] myArray) { 
    myArray = new string[] { "world" }; 
} 

パラメータは、常にによって渡されますあなたがrefまたはoutのキーワードを使用しない限り、参照型の場合、参照のコピーを渡すことを意味します。

public static void TestMethod(ref string myString) { 
    myString = "world"; 
} 
関連する問題