ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

C#コミュのconst や readonly の配列はNG?

  • mixiチェック
  • このエントリーをはてなブックマークに追加
定数の配列を用意したいのですが、constだとコンパイル時にエラーが発生してしまい、readonlyだとコンストラクタ以外の場所でも値を変更できてしまうんですが何か良い方法はないでしょうか?

---------------------------------------------------
コンパイル時にエラー
○const int value = 1;
×const int[] valueArray = { 1,2,3 };

---------------------------------------------------
○readonly int value = 1;
△readonly int[] valueArray = new int[3];

エラーは検出されないけどコンストラクタ以外でも値を変更できてしまう

コンストラクタで初期化する
valueArray[0] = 0;
valueArray[1] = 1;
valueArray[2] = 2;

コンストラクタ以外の場所でも変更できてしまう ><
valueArray[0] = 5;

コメント(20)

的外れかも知れませんが・・・。
getプロパティを使うのはどうでしょうか。

private static int[] valueArray
{
get
{
int[] reval = {1, 2, 3};
return reval;
}
}

これくらいしか思いつきませんでした・・・。
クラスでインデクサと readonly なプロパティじゃダメすか?
>青海苔
getプロパティを使用するとそのクラスの外からは確かに読み取り専用になりますが、自分がやりたいのはそのクラス内でも読み取り専用にしたいのです。

>shinchan55
列挙型では配列は作れませんよね。
AsReadOnlyは知りませんでしたが、ラップしてない元の変数をいじられたらそれまでだし・・・


一応簡単なクラスや構造体を使えば実現できるとは思うのですが、ただ定数配列を作るのにそんなやり方しかないのかなと・・・。

例はint型で書きましたが、string型の定数配列とかみなさんはあまり使わないのでしょうか?

良い例が浮かびませんが例えば一週間の曜日の配列とか・・・。
色んな所に"月曜日"と書くのは良くないと思うのでどこか1箇所で定義しますよね?曜日は不変的なので const にしたいし、曜日は並んでいるので配列だと理想だと思うのですが・・・。
>一応簡単なクラスや構造体を使えば実現できるとは思うのですが、ただ定数配列を作るのにそんなやり方しかないのかなと・・・。

この発想は妙です(^▽^;)
逆に伺いますが、何故クラスじゃダメなんでしょうか?

独自のイベントハンドラで独自のイベント引数の引渡しをするのもオブジェクト単位ですし、ごく普通のやり方だと思いますが。
やりたいことが単純な事なのでクラスにはしたくないのです。
実際に一週間の例をクラスで作ってみると...

---------------------------------------------------
意味的にはこれを実現したい。
const string[] weekArray = {"月曜日","火曜日"...};
weekArray[0] = "土曜日"; // エラーとなり変更できない

---------------------------------------------------
これをクラスで実現しようとすると
まずはコンストラクタでしか設定できないクラスを作り...
public class ReadonlyClass
{
  private readonly string m_sText;

  public string Text
  {
    get{ return m_sText; }
  }

  // コンストラクタでしか設定できない
  public ReadonlyClass( string sText )
  {
   m_sText = sText;
  }
}

そしてインスタンスを作成していく・・・
ReadonlyClass[] weekArray = new ReadonlyClass[7];

weekArray[0] = new ReadonlyClass( "月曜日" );
weekArray[1] = new ReadonlyClass( "火曜日" );

ここでエラーになるので定数配列ができたけど・・・
weekArray[1].Text = "土曜日";

面倒・・・><
---------------------------------------------------
これだったら配列をあきらめるか・・・
const string monday = "月曜日";
const string tuesday = "火曜日";

---------------------------------------------------
もしくは定数をあきらめるか・・・
(大抵の人はこれだと思う)
string[] weekArray = {"月曜日","火曜日"...};

---------------------------------------------------
でもできれば簡単に定数配列を使いたいので・・・何かいい方法を知ってる人がいるかなと。
>enum DAY{日,月,火,水,木,金,土} としておいて、

え、日本語も設定できるんだ!
面白いけどかなりトリッキーな気が・・・><
>え、日本語も設定できるんだ!

メソッド名を日本語で書いている人も珍しくないですよ。
派生クラスでオーバーライドする時、訳わからなくなるので、僕はあまり使わないですが、こういう場合は僕も日本語を使います。

例は汎用性を求めていますが、特化して使うクラスにサブクラスとして置けばいいと思うのですが。
  private class WeekArray {
   string[] weekText = {"日","月","火","水","木","金","土"};
   public string this[int index] {
     get {
      return this.weekText[index];
     }
   }

  }
  WeekArray weekArray = new WeekArray();
呼び出し側はどういうのを想定しているんでしょうか?
ちょっと配列にこだわる理由が分かりません。

class Week {
public const string 日 = "日曜日";
public const string 月 = "月曜日";
(略)

public static IEnumerable<string> Enumerator {
get {
yield return "日曜日";
yield return "月曜日";
(略)
}
}

}
なるほど。やっぱりクラスなどを使うのが基本みたいですね。
でも色々なやり方がありそうなので大変参考になりました。
ありがとうございます。<(_ _*)>
もはや enum は裏では数値として扱ってるけど、表は文字列そのものだと思ってます。

namespace MyNamespace
enum 曜日 {
日 = 0,
月 = 1,
火 = 2,
水 = 3,
木 = 4,
金 = 5,
土 = 6,
};
}

使用例:
MyNamespace.曜日 w = MyNamespace.曜日.月;

int x = (int)w; // 数値がほしい
string s = w.toString(); // 文字列がほしい

IntellisenseのおかげでVisualStudio上だったら普段は選ぶだけです。
定数部分をわざわざ書くのは後でずれると困るから。
>14
static でインデクサって使えるんですね。
this[] で再定義するからてっきり無理なんだと思ってました(^^)

>16
>もはや enum は裏では数値として扱ってるけど、表は文字列そのものだと思ってます。

う〜む、この考え方は、ちょっと危険ですね。
enum は数値なんだということを常に念頭に置いて使わないと「アレ?」ということになることがしばしばでてくると思うんですが。

ちなみに2005からは、何故か enum の toString() の使用は推奨されなくなっているので、僕は、Enumクラスから文字列を取得するようにしてます。
ていうか、曜日なんかわざわざ定義しなくても
Enum System.DateTime.DayOfWeek
ていうのがあったとオモ
>honestaholic
最近のレスだけを見てみると曜日の定義方法と見られてしまうかもしれないですけど、不変的な配列定義の例として分かりやすい曜日を挙げているだけですよ。

ログインすると、残り7件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

C# 更新情報

C#のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング