- PR -

OptionStrict に関してご指摘ください。

1
投稿者投稿内容
NVL
常連さん
会議室デビュー日: 2006/04/03
投稿数: 45
投稿日時: 2007-04-07 11:51
いつもお世話になっております。
VB2005で以下のようなコーディングをしております。
先日、OptionStrictをOnにしたらコンパイルエラーが発生しました。

===登場するオブジェクト===
(親パラメータ)クラス
 処理用Inputパラメータ格納クラスのラッパー。クラス宣言のみで中身は記述していない。
(子パラメータ)クラス
 処理用Inputパラメータ格納クラス。各処理ごとに定義。親パラメータを継承している。
(ロジック)インターフェイス
 業務ロジック用クラスでのメソッドを定義している。
(ロジック実装)クラス
 ロジックインターフェイスの実装クラス。各業務ロジックごとに作成する。
          
///////////////////////以下コーディング///////////////////////
'処理用Inputパラメータの準備
Dim objPm As New 子パラメータ
With objPm
.ID = strUserId
.Pass = strPass
End With
'Inputパラメータを引数に渡して業務ロジックを実行
Dim objLogic As ロジック = New ロジック実装
objLogic.Execute(objPm)  '←ここで「暗黙の型変換ができない」というエラー発生
///////////////////////コーディング終了///////////////////////

上記コーディングのエラー箇所、Executeメソッドでは(親パラメータ)クラスを
ByRef引数として定義しております。引数を CType(objPm,親パラメータ) として
渡してやれば解決するのですが、私としては「元々、親で定義している引数に子を渡す
のに、なんで変換しないといけないの?その逆なら分かるけど」という思いがあります。
また、ByValで渡しにしてやっても解決できますが、「オブジェクトをByValで渡さんで
しょう」という認識でやっております。

私の認識誤りをご指摘ください。よろしくお願い致します。
にー
常連さん
会議室デビュー日: 2006/04/30
投稿数: 35
投稿日時: 2007-04-07 12:11
ロジック実装のExecuteメソッドの引数のクラスは何ですか?
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2007-04-07 12:20
> 「オブジェクトをByValで渡さんでしょう」
参照型を値渡し(ByVal)することは一般的なことです。
むしろ、参照型を参照渡し(ByRef)することの方が一般的ではない(やるべきではない)と思います。
参照型を参照渡しするということは、参照の参照を渡しているわけで、オブジェクトそのものをすり替えられることになってしまいます。

# VBコンパイラの挙動はよくわかりませんのでそちらはあえて触れません^^;
NVL
常連さん
会議室デビュー日: 2006/04/03
投稿数: 45
投稿日時: 2007-04-07 12:39
みなさま、早速のご回答、ありがとうございます。

にー様
>ロジック実装のExecuteメソッドの引数のクラスは何ですか?

引数は(親パラメータ)クラスになっております。
とりあえず親パラメータとして渡しておいて、実装側で
縮小変換して取り出すようにしております。

よこけん様
>参照型を値渡し(ByVal)することは一般的なことです。

え!?そうなんですか・・・・。私は「渡した先で値が変更されちゃまずい!!」
っていう場合以外は、参照渡しに”すべき”だと思っていました。不必要に
コピー領域を増やすのもどうかな、とう思いからなんですが。

引き続き、ご指摘のほどをよろしくお願いします。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-04-07 12:56
引用:

え!?そうなんですか・・・・。私は「渡した先で値が変更されちゃまずい!!」
っていう場合以外は、参照渡しに”すべき”だと思っていました。不必要に
コピー領域を増やすのもどうかな、とう思いからなんですが。


「参照渡し/値渡し」と「参照型/値型」は別物です。
参照型の場合、値渡しする時はそのインスタンスの参照の値を(コピーして)渡します。インスタンスそのものはコピーされず、呼び出し元と呼び出し先では同じインスタンスを参照します。

引用:

引数は(親パラメータ)クラスになっております。
とりあえず親パラメータとして渡しておいて、実装側で 縮小変換して取り出すようにしております。


これは色々問題がある実装のように思えますね。
もしロジック実装に親パラメータクラスから派生した別のパラメータクラスインスタンスを渡したくなったらどうするんですか?
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2007-04-07 13:09
参照型と値型、参照渡しと値渡しについて、正確に理解することをお勧めします。
※Hongliangさんもおっしゃってますが、型と渡しは「別の概念」なんですよね。

で、参照渡しでは、基本的に同じ型しか渡すことはできません。
なぜかというと、呼び出し先で代入される可能性があるからです。
※子クラスを渡したときに、渡された側で子2クラスを代入してしまうとどうなるでしょう?

--追記
メソッドに「渡すデータ」とメソッドから「受け取るデータ」では、
型の制約が逆になることを思い浮かべると分かりやすいかもしれません。

渡すデータの型はメソッド定義の子クラスでもいですが、
戻り値を受け取る変数の型は、メソッド定義の型か親クラスでないとだめですよね。

参照渡しというのは、渡すことと受け取ることを同時に行う引数なので、
結局定義と同じ型でないと、両方のルールを守ることができないんですね。


[ メッセージ編集済み 編集者: なちゃ 編集日時 2007-04-07 13:16 ]
IIJIMAS
ベテラン
会議室デビュー日: 2006/12/06
投稿数: 77
投稿日時: 2007-04-07 13:24
出遅れました…
もうすでに皆様が書かれておられますが、
ByRefだと、メソッドを抜けるときに、
DreamTheater様自身が書かれている
引用:

その逆なら分かるけど


”その逆”も起きます。


[ メッセージ編集済み 編集者: IIJIMAS 編集日時 2007-04-07 13:24 ]
NVL
常連さん
会議室デビュー日: 2006/04/03
投稿数: 45
投稿日時: 2007-04-07 14:43
皆様、ご回答ありがとうございます。

Hongliang様
>もしロジック実装に親パラメータクラスから派生した別のパラメータクラスインスタンスを渡したくなったらどうするんですか?

今回、パラメータインスタンスとロジック実装は1対多の関係を前提としております。
オブジェクト設計に関してはあまり突っ込まないでください。いや、
突っ込んで欲しい気持ちは山々なんですけどね。初めてなので。私にとっても会社に
とっても(爆)。

さて、Hongliang様よりご指摘がありましたように、私、型と渡しを混同しておりました。
また、なちゃ様、IIJIMAS様からのご指摘より、「参照渡しで、実際に渡した型より
大きいものを渡した先で代入された場合」について、初めて気づくことができました。
よこけん様からの
>オブジェクトそのものをすり替えられることになってしまいます。
というのも、これで納得がいきました。

かれこれ4年ほど誤った認識でいたことに関しては恐ろしいやら恥ずかしいやらといった
感じですが、なぜかちょっと嬉しくて興奮しております。

というわけで、「最悪、OptionStrictはOFFで行こう」という方向になっていたのを
撤回できそうです。どうも有難うございました。
1

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