.NET TIPS

[ASP.NET]アプリケーション全体で共有するデータを扱うには?(静的メンバ編)

デジタルアドバンテージ
2004/02/13

 「TIPS:[ASP.NET]アプリケーション全体で共有するデータを扱うには?(Applicationオブジェクト編)」では、アプリケーション全体で共有するデータをApplicationオブジェクトに格納する方法について解説した。しかし記事の最後にも記述したように、本来Applicationオブジェクトは、従来のASPとの互換性のために用意されているものである。ASPでは、VBScriptにグローバル変数(各ページのインスタンスからアクセス可能な共通の変数)がなかったためこのような機能が導入されていたが、C#やVB.NETでは静的メンバが使えるため、実際にはApplicationオブジェクトを使う必要はない。むしろ静的メンバを利用した方がパフォーマンスは向上する場合がある*1

*1 参考情報:「[INFO] ASP.NET のアプリケーション インスタンス、アプリケーション イベント、およびアプリケーション状態」)

 本稿では静的メンバを利用して、アプリケーション全体で共有するデータの扱い方について解説する。アプリケーション全体からアクセス可能な静的メンバとは、具体的には、Global.asaxで宣言されたpublicでstaticな変数(VB.NETの場合にはPublicでSharedな変数)である。

 Applicationオブジェクト編と同様に、共通の定数として利用する場合と、共通の変数として利用する場合の2つについて見ていこう。

共通の定数として静的メンバを使用する

 共通の定数として静的メンバを使用するには、Visual Studio .NETを利用している場合、Global.asaxファイルにコードビハインドにより関連付けられているGlobal.asax.vb(C#の場合にはGlobal.asax.cs)で自動的に作成されるクラス「Global」において、次のようにして読み出し専用となる変数をまず宣言する(VB.NETの場合)。これはクラス内で、かつメソッドの外部に記述する必要がある。

Public Shared ReadOnly Title As String = "在庫管理アプリケーション"

 C#では、このコードは次のようになる。

public static readonly string Title = "在庫管理アプリケーション";

 定数として利用する場合には、変数をReadOnly(C#ではreadonly)として宣言することにより、(Applicationオブジェクトと違って)真に読み取り専用として利用できる。

 上記のコードを実際にVisual Studio .NET(使用言語はVB.NET)で記述している画面を次に示す。

Visual Studio .NETで編集中のGlobal.asaxファイル
コードビハインドにより、実際のコードはGlobal.asaxに関連付けられているGlobal.asax.vbに記述する。
  Global.asaxを選択して、コードを表示させる。
  Globalクラス内のフィールドで静的メンバを宣言する。

 この定数を読み出すWebページのコードは次のようになる(あらかじめWebフォームにLabelコントロールを配置しておく必要あり)。

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  ' ページを初期化するユーザー コードをここに挿入します。
  Label1.Text = Global.Title
End Sub
静的メンバの値を読み出し、Labelコントロールに表示するVB.NETのコード
(実際に記述するコードは太字の部分のみ)
 
private void Page_Load(object sender, System.EventArgs e)
{
  // ページを初期化するユーザー コードをここに挿入します。
  Label1.Text = Global.Title;
}
静的メンバの値を読み出し、Labelコントロールに表示するC#のコード
(実際に記述するコードは太字の部分のみ)

 宣言時に型が決まっているため、Applicationオブジェクトでは必要だったキャスト(CType関数による型の変換)は不要である。なお、すでに述べているように「Global」はVisual Studio .NETにより自動生成されたクラスの名前である。

 以上のようにして静的メンバを共通の定数として使用する方法をApplicationオブジェクトと比較した場合、Applicationオブジェクトは以下のような理由でパフォーマンスが悪い。

  • Applicationオブジェクトではキーとなる文字列によりコレクション内を走査する必要がある

  • Applicationオブジェクトのコレクションに値型の値(数値など)を格納する場合にはボックス化が必要

  • Applicationオブジェクトには読み出し専用として利用するための機能がないため、読み出し時にもオブジェクトはロックされる

静的メンバを読み書きするにはロックが必要

 静的メンバを共通の変数として使用する場合には、Applicationオブジェクトと同様に排他処理が必要になる。ここでは、あるページにおいて、そのページがアクセスされた総数を静的メンバでカウントし、それを表示する場合について見てみる。

 まず、先ほどと同様に、Global.asax.vbのGlobalクラスで、カウンタとなる変数Counterを宣言し初期化する(次の画面はVB.NETの場合)。

ページ・カウンタとなる変数CounterをGlobalクラスで宣言

 一方、変数Counterの値を1つ増やし、それをLabelコントロールに表示するためのコードは次のようになる。

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  ' ページを初期化するユーザー コードをここに挿入します。
  SyncLock GetType(Global)
    Global.Counter = Global.Counter + 1
  End SyncLock
  Label1.Text = "カウンタ:" & Global.Counter
End Sub
ページ・カウンタをインクリメントしてから表示するためのVB.NETのコード
SyncLockステートメントにより、ほかのセッションからGlobal.Counterにアクセスできないようにしてから値を更新する必要がある。
 
private void Page_Load(object sender, System.EventArgs e)
{
  // ページを初期化するユーザー コードをここに挿入します。
  lock (typeof(Global))
  {
    Global.Counter = Global.Counter + 1;
  }
  Label1.Text = "カウンタ:" + Global.Counter;
}
ページ・カウンタをインクリメントしてから表示するためのC#のコード

 SyncLockステートメント(C#ではlockステートメント)は、パラメータで指定されたオブジェクトをロックして、ほかのセッション(ほかのユーザーによるアクセス)と同期するためのものだ。また、パラメータに指定しているGetType(Global)は、GlobalクラスのTypeオブジェクト(Typeクラス(System名前空間)のオブジェクト)を取得するためのものである。

 グローバルな静的メンバとして、参照型であるオブジェクトを利用している場合にはSyncLockステートメントのパラメータにそのオブジェクトそのものを記述すればよいが、今回の例では値型であるInteger型を使用しているため「SyncLock Global.Counter」とは記述できない。そのため、ここではGlobalクラスのTypeオブジェクトを取得し、それをロックの対象としている。通常、1つのWebアプリケーションにおいては、GetType演算子により得られるTypeオブジェクトは常に同じオブジェクトである。

 上記のコードでは、ある1つのセッションが「SyncLock 〜 End SyncLock」の部分を実行している間は、この部分のコードを実行しようとするほかのセッションは待つことになる。このためGlobal.Counterの値を確実に+1することができる。End of Article

カテゴリ:Webフォーム 処理対象:Global.asax
使用ライブラリ:Typeクラス(System名前空間)
関連TIPS:[ASP.NET]アプリケーション全体で共有するデータを扱うには?(Applicationオブジェクト編)
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]アプリケーション全体で共有するデータを扱うには?(Applicationオブジェクト編)
構文:定数(変更できないもの)を作るには?[C#/VB]
コントロールのメンバ変数を自動生成させないようにするには?
列挙体の値を列挙するには?
Windowsフォームで簡単に画像を表示するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間