- PR -

【VB.Net2008】循環参照について

1
投稿者投稿内容
うちうせん
ベテラン
会議室デビュー日: 2003/08/08
投稿数: 96
お住まい・勤務地: 福岡県
投稿日時: 2008-07-21 14:22
現在、循環参照について悩んでいます。
現状は・・・
-------------------------------------------------------------------
FormBase(メニュー)
FormA
FormB
があり
FormA・FormBはFormBaseを継承している
(ここでFormA→FormBase/FormB→FormBaseの参照が発生)
FormAからFormBを呼ぶ際に、FormBaseのメニューにて呼ぶことになる
(ここでFormBase→FormBの参照が発生)
同様にFormBからFormAを呼ぶ場合もある
(ここでFormBase→FormAの参照が発生)
FormBase⇔FormA/FormBase⇔FormBの循環参照が発生する(?)
-------------------------------------------------------------------
@上記の例はそもそも循環参照になるんでしょうか?
A循環参照を行なうとメモリリークが発生するようなことを見たのですが、
メモリリーク以外にも問題があるでしょうか?
B何か解決策の例などがあれば教えてください。
(FormAとFormBをExe化することも考えたのですが、相互遷移と表示状態の維持
を考えると難しいかも?)

以上、アドバイスよろしくお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-07-21 16:08
(VB.NET は知りませんが。)

> FormA・FormBはFormBaseを継承している
> (ここでFormA→FormBase/FormB→FormBaseの参照が発生)
> FormAからFormBを呼ぶ際に、FormBaseのメニューにて呼ぶことになる
> (ここでFormBase→FormBの参照が発生)

> 上記の例はそもそも循環参照になるんでしょうか?

まず、継承は循環参照に関係ありません。
「呼ぶ」こと自体も循環参照に関係ありません。
「参照」こと自体も循環参照に関係ありません。
ただし、参照する際にフィールドに入れて、それを互いに持ち合うと循環参照になります。(A→B→(もとの)A、や A→B→C→(もとの)A のように。)

> 循環参照を行なうとメモリリークが発生するようなことを見たのですが、
> メモリリーク以外にも問題があるでしょうか?

VB6やそれより前や、VBScript だとたしかにメモリーリークになりました。なお、メモリリーク以外には別段(?)、問題はなかったと思います。

VB.NET(VB2005)では、循環参照という話題は聞かないので、起きないのだと思います。(循環参照は起きても、ほかからの参照がなくなれば、消滅してしまい、メモリーリークにならないという意味です。)

> 何か解決策の例などがあれば教えてください。
> (FormAとFormBをExe化することも考えたのですが、相互遷移と表示状態の維持
> を考えると難しいかも?)

メモリーリークになるかどうか、という観点からだけ言えば、なにも問題はないし、メモリーリークもしないので、なにも解決策をとる必要はないでしょう。
ただし、循環参照というものはそう頻繁に使うものではないので、循環参照は設計が変かもしれないと考えてリファクタリングしたほうが良いことが多いです。もっとも、本当に必要な循環参照もあります。



#以下、追記。

> 上記の例はそもそも循環参照になるんでしょうか?

について書き忘れましたが、コードがないので良く分かりません。
ちなみに、昔の VB の循環参照の解説は、英語ですがつぎのようなものです。(昔は日本語のページもあったのですが、今探したら見当たりませんでした。)
http://msdn.microsoft.com/en-us/library/aa716190.aspx

クラスのフィールドだけに着目すれば、循環参照かどうかは大体判別できます。

[ メッセージ編集済み 編集者: unibon 編集日時 2008-07-21 16:34 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-07-21 23:17
「COM の循環参照」 と何かを混同しているような気がしますね。 アセンブリの相互参照と混同しているパターンならともかくとして、今回のようなパターンは珍しいですね。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2008-07-22 01:39
引用:

FormBase(メニュー)
FormA
FormB


が別々のアセンブリになってるとか?
FormBase にメニューって書いてあるけれど FormBase から FormA が呼ばれる??
メニューも FormBase の派生クラスな気がする。でもこれでも良いのか?
_________________
かるあ のメモスニペット
うちうせん
ベテラン
会議室デビュー日: 2003/08/08
投稿数: 96
お住まい・勤務地: 福岡県
投稿日時: 2008-07-22 07:12
unibonさん・じゃんぬねっとさん・かるあさん
返答ありがとうございました。

ちょっと書き方が悪かったみたいで・・・
かるあさんのおっしゃるとおり
FormBase→exe
FormA→dll
FormB→dll
と3つ別のアセンブリになっています。
FormBase(メニュー)
というのはFormBaseにメニューを配していて、そのメニューからFormA・FormBを呼ぶということです。
具体的には派生させたFormAからになるのですが・・・

じゃんぬねっとさんの言われている「COM の循環参照」 と「アセンブリの相互参照」ってどういうことでしょうか?
勉強不足ですみません。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-07-22 09:24
引用:

うちうせんさんの書き込み (2008-07-22 07:12) より:
FormBase(メニュー)
というのはFormBaseにメニューを配していて、そのメニューからFormA・FormBを呼ぶということです。
具体的には派生させたFormAからになるのですが・・・



FormBase(親)はFormA(子)、FormB(子)のことは知りません。
FormA(子)、FormB(子)はFormBase(親)を知っています。

ですので、FormBaseのソースコードの中では、
Dim f As FormBase
f = New FormA()
のような記述はできませんし、しません。

今回のようなパターンでは、Xmlファイルやデータベースに
・メニュー上の名称、FormAを含むアセンブリ名、FormAの完全限定名
・メニュー上の名称、FormBを含むアセンブリ名、FormBの完全限定名
などを登録しておき、これらの情報を元にリフレクションでFormAやFormBのインスタンスを生成します。
生成したインスタンスはFormBase型の変数に入れて扱います。

なので、FormAを含むアセンブリ、FormBを含むアセンブリはFormBaseを含むアセンブリを参照する必要がありますが、その逆は必要ありません。
sasagaki
常連さん
会議室デビュー日: 2008/03/10
投稿数: 20
投稿日時: 2008-07-22 15:26
画面遷移に関する要件は

(1)メニューから、FormA、FormBを呼ぶ。
(2)FormAから、FormBを呼ぶ。
(3)FormBから、FormAを呼ぶ。

ということでよろしいのでしょうか。

そして、さらに、

(4)FormAとFormBは、FormBaseという共通な画面を継承したい。
(5)FormBaseが、メニューを兼ねている。

ということでしょうか?

うちでは、今、似たようなシステムを開発していますが(VB.NET 2005ですが)、
次のような方法で実現できております。

・継承元フォームFormBaseは、メニューexeとは別のDLLに切り出し、FormA、FormBはこれを継承する。
・画面遷移するときは、遷移先画面のインスタンスを生成してShowするのではなく、常に、「○○画面に遷移したいよ!」というイベントを発行するだけにする。
・イベントを捕捉するためのクラスをexeに用意し、イベントを捕捉したら、しかるべき画面のインスタンスを生成してShowする。

参照は次のようになります。

・FormBase.DLL・・・何も参照しない
・FormA.DLL・・・FormBase.Dllを参照
・FormB.DLL・・・FormBase.Dllを参照
・exe・・・FormA.DLL、FormB.DLLを参照



うちのケースでは、FormBase=メニュー画面、ではないので、うちうせんさんのケースに当てはまるかどうかは分かりませんが、参考になれば。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2008-07-22 20:03
こんばんは。

引用:

うちうせんさんの書き込み (2008-07-21 14:22) より:
現在、循環参照について悩んでいます。



循環参照 (Wikipedia)

引用:

@上記の例はそもそも循環参照になるんでしょうか?



まず何をもって”参照”とおっしゃっているのか、はっきりして欲しいところです。
 A.オブジェクト変数にオブジェクト(インスタンス)の参照を代入すること?
 B.アセンブリの参照設定のこと?

引用:

A循環参照を行なうとメモリリークが発生するようなことを見たのですが、
メモリリーク以外にも問題があるでしょうか?



”参照カウント”方式のガベージコレクションには、”循環参照”の問題(メモリリーク)があります。
ここでいう”参照”とは、「A.オブジェクト変数にオブジェクト(インスタンス)の参照を代入すること」のことです。
参照カウント (Wikipedia)

”参照カウント”方式であるCOM(Component Object Model)や、COMをベースにしているVB6以前では、”循環参照”の問題がありました。

.NET Frameworkの共通言語ランタイム(CLR)では、トレース方式(マークアンドスイープ/世代別ガベージコレクション)なので、”循環参照”に配慮する必要はありません。
1

スキルアップ/キャリアアップ(JOB@IT)