Garbage Collection

塵も積もれば山

目次

Blog 利用状況

ニュース

C++とかC#とか数学ネタを投下していく予定です。

[その他のページ]
日々の四方山話を綴った日記出水の日記帳

書庫

日記カテゴリ

[C#].Netの器

ネタ元>[日常][C/C++][VB]VBでこんな書き方出来るの?

void test1(){
  char str1[] = "aaaa";
  char str2[] = "bbbb";

  char *array[] = {str1, str2};
  for (int i=0; i<2; i++){
    strcpy(array[i],"cccc");
  }

  printf("%s\n", str1);  // "cccc"が表示される事を期待
  printf("%s\n", str2);  // "cccc"が表示される事を期待
}

void test2(){
  char *str1 = "aaaa";
  char *str2 = "bbbb";

  char **array[] = {&str1, &str2};
  for (int i=0; i<2; i++){
    *array[i] = "cccc";
  }

  printf("%s\n", str1);  // "cccc"が表示される事を期待
  printf("%s\n", str2);  // "cccc"が表示される事を期待
}

Cのコードはこのどちらかを意図していると思います。
でも、双方のコードは結果は同じでもやってることが違います。

test1の関数は、str1,str2を変更することができないので
str1,str2が参照しているデータを書き換えています。

test2の関数は、str1,str2のアドレスを持っているため、
この変数そのものの値を書き換えています。

test1 の様子 test2の様子

で、.Netのコードでこれをやろうとすると、どっちもできません。

test1の方法ではString型がReadonlyのため書き換えることができず、
test2の方法ではアドレスを取得できないため、
str1,str2に別名でアクセスする方法がありません。

ただ、test1の方法でString以外を使う方法でなら実現できます。
たとえばStringBuilderを使ったらこんな感じ。

static void Test1(){
  var str1 = new System.Text.StringBuilder("aaaa");
  var str2 = new System.Text.StringBuilder("bbbb");

  System.Text.StringBuilder[] array = { str1, str2 };

  for (int i = 0; i < 2; i++){
    array[i].Remove(0, array[i].Length);
    array[i].Append("cccc");
  }

  Console.WriteLine(str1);
  Console.WriteLine(str2);
}

StringBuilderは全部置き換えを目的に作られてないため、
RemoveしてAppendという情けないコードになってますが…。

ただ、こんな苦し紛れなことをするよりは、器に入れて持ち運んでやるべきでしょうね。

public class Carrier{
  public T value;
  public Carrier(T x){
    value = x;
  }
}

static void Test2()
{
  var str1 = new Carrier("aaaa");
  var str2 = new Carrier("bbbb");

  Carrier[] array = { str1, str2 };

  for (int i = 0; i < 2; i++){
    array[i].value = "cccc";
  }

  Console.WriteLine(str1.value);
  Console.WriteLine(str2.value);
}

#まだ.Net Refrector入れてないのでVBじゃなくてC#だけど…

投稿日時 : 2009年1月14日 20:47

Feedback

# re: [C#].Netの器 2009/01/14 21:23 774RR

別にけちをつける気は無いんだけど C の解説のその図、あまりよくない。
というより嘘。
test1 の str1 str2 のこの図示や、以下の文の文言
> test1の関数は、str1,str2を変更することができないので
> str1,str2が参照しているデータを書き換えています。
俺の後輩君がこういう説明したら点数あげられないよ。

test1 の str1 は「配列」なので、俺が解説書くなら
「str1 str2 (の中身)を変更することができる」
とする。

「str1 が参照するデータ」など存在しない。
「str1 に入っているデータ」なら存在する。
str1 はポインタぢゃない。あくまで配列。

str1 の配列名が暗黙変換でポインタに自動変換されているだけ。

# [C++/CLI]私の特技は追跡参照です 2009/01/14 21:27 Garbage Collection

[C++/CLI]私の特技は追跡参照です

# re: [C#].Netの器 2009/01/14 21:45 出水

私なら中身と言おうが参照と言おうが点をあげるなぁ~
ま、そういうもんです

タイトル
名前
Url
コメント