C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: VB6の参照渡し


(過去ログ 80 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■47434 / inTopicNo.1)  VB6の参照渡し
  
□投稿者/ tonton (19回)-(2010/03/02(Tue) 15:07:46)

分類:[VB6 以前] 

下のサンプルの子関数内にて呼び出し元の値を変えたいのですが、
String型の変数値やTextBoxオブジェクトなどを引数にしても利用できるようにしたいのです。
下のサンプルのコーディングを変える事なく実現可能でしょうか?
一旦
str = TEXTBOX.Text
としてから
Ret = MOJISET(str)
するしか思い浮かびません。できればコールするステップ以外を増やしたくないのですが・・・

'呼び出し元側処理
Dim Ret As Integer
Dim str As String

Ret = MOJISET(TEXTBOX.Text)

Ret = MOJISET(str)
など


'子関数サンプル
Function MOJISET(moji)

moji = "A"
MOJISET = 0
End Function
引用返信 編集キー/
■47440 / inTopicNo.2)  Re[1]: VB6の参照渡し
□投稿者/ 魔界の仮面弁士 (1517回)-(2010/03/02(Tue) 16:40:04)
No47434 (tonton さん) に返信
> 下のサンプルの子関数内にて呼び出し元の値を変えたいのですが、
できればイメージコードでは無く、実際のコードに近い物を転記していただけると助かります。
  Text1 でも TextBox1 でもなく、TEXTBOX というコントロール名。
  Str関数と被るような STR という変数名。
  引数の型を明示していない Function。
  戻り値の型を明示していない Function。
  戻り値が常に固定値 0 を返すだけの Function。
いずれも文法的には正しいですが…実コードもそうなっているのでしょうか?


> 下のサンプルのコーディングを変える事なく実現可能でしょうか?
「呼び出す側」と「呼び出される側」、そのどちらも変更したくないという事でしょうか?
それは流石に不可能だと思いますよ。

どちらか片方に手を加えても良いのだとすれば、こういうのは如何でしょうか。


Option Explicit

' MODE = 0  : 元の実装
' MODE = 1  : 修正案1
' MODE = 2  : 修正案2
#Const MODE = 1

Private Sub Command1_Click()
    Dim Ret As Integer
    Text1.Text = "Old Value"
    Ret = MOJISET(Text1)
    MsgBox CStr(Ret) & vbCrLf & Text1.Text
End Sub

Private Sub Command2_Click()
    Dim Ret As Integer
    Dim s As String
    s = "Old Value"
    Ret = MOJISET(s)
    MsgBox CStr(Ret) & vbCrLf & s
End Sub

Private Sub Command3_Click()
    Dim Ret As Integer
    Dim v As Variant
    v = "Old Value"
    Ret = MOJISET(v)
    MsgBox CStr(Ret) & vbCrLf & CStr(v)
End Sub


#If MODE = 1 Then

Function MOJISET(ByRef moji As Variant) As Variant
    If TypeOf moji Is TextBox Then
        moji.Text = "A"
    Else
        moji = "A"
    End If
    MOJISET = 0
End Function

#ElseIf MODE = 2 Then

Function MOJISET(ByRef moji As Variant) As Integer
    If TypeOf moji Is VB.Control Then
        Dim c As Control
        Set c = moji
        Let c = "A"
    ElseIf IsObject(moji) Then
        Dim o As Object
        Set o = moji
        Let o = "A"
    ElseIf VarType(moji) = vbString Then
        moji = "A"
    Else
        Err.Raise 5
    End If
    MOJISET = 0
End Function

#Else

Function MOJISET(moji)
    moji = "A"
    MOJISET = 0
End Function

#End If

引用返信 編集キー/
■47441 / inTopicNo.3)  Re[2]: VB6の参照渡し
□投稿者/ tonton (20回)-(2010/03/02(Tue) 17:04:12)
No47439 (魔界の仮面弁士 さん) に返信
> ■No47434 (tonton さん) に返信
>>下のサンプルの子関数内にて呼び出し元の値を変えたいのですが、
> できればイメージコードでは無く、実際のコードに近い物を転記していただけると助かります。
>   Text1 でも TextBox1 でもなく、TEXTBOX というコントロール名。
>   Str関数と被るような STR という変数名。

すいません。これは以後気をつけたいと思います。。。

>   引数の型を明示していない Function。
>   戻り値の型を明示していない Function。
>   戻り値が常に固定値 0 を返すだけの Function。
> いずれも文法的には正しいですが…実コードもそうなっているのでしょうか?

戻り値は正常、エラーの値ぐらいは返しています。
元のソースは禁則文字の置き換えで使用しています。
型の明示はありません。しかも現在運用されてしまっています(汗)

>>下のサンプルのコーディングを変える事なく実現可能でしょうか?
> 「呼び出す側」も「呼び出される側」、そのどちらも変更したくない、という事ですか?
> それは流石に不可能だと思いますよ。

「呼び出される側は変更したくない」が希望です。
呼び出す側は私の修正方法が一般的かつ少ないステップで済んでいるのであればそれでいこうと思っています。

事情としてはこの子関数を呼び出している箇所が100箇所あったとしてString型の変数を引数にしているところが
90箇所、残りの10箇所はTextBoxのTextプロパティを直接引数にしていて、これが値の変換がうまくいっていないのです。
魔界の仮面弁士さんの案の内容は理解しましたし、私もそれに近い修正を提案したところ子関数を修正すると
残りの90箇所にも影響が出る!という事でなんとか呼び出し側で対応できないか?という事なんです。
元々子関数の作り自体あまりよろしくないのは重々承知の上で今3案で迷っている参考にしたかったのです。
案1.既存の子関数をコピってTextBox用の子関数を別途作る。
案2.10箇所に私が考えたようなString型に一度セットしてから引数で渡し、戻った値をまたTextBoxにセットする。
案3.子関数を修正する(これが本当は一番いい気がするのですが、今回は一番影響があるのでやりたくない上の意向)


引用返信 編集キー/
■47448 / inTopicNo.4)  Re[3]: VB6の参照渡し
□投稿者/ 魔界の仮面弁士 (1519回)-(2010/03/02(Tue) 19:38:38)
No47441 (tonton さん) に返信
> 「呼び出される側は変更したくない」が希望です。
VB.NET ならば良かったのですけれどね…。


> 型の明示はありません。しかも現在運用されてしまっています(汗)
ByVal/ByRef/As を明示するよう、開発ルールを定めておいた方が良いですよ。
VB6 による“新規の”開発案件があるのならば、ですけれども。


> 事情としては
(中略)
> 私もそれに近い修正を提案したところ子関数を修正すると
そういう事は最初に書いてください。。。(T_T)


> 事情としてはこの子関数を呼び出している箇所が100箇所あったとしてString型の変数を引数にしているところが
> 90箇所、残りの10箇所はTextBoxのTextプロパティを直接引数にしていて、これが値の変換がうまくいっていないのです。
Variant 型の変数を渡している所は無いのですね?


> 残りの90箇所にも影響が出る!という事でなんとか呼び出し側で対応できないか?という事なんです。
とはいえ、「確かに、何も影響が無かった」という事を確認するために、
100箇所すべてテスト対象に含めておいた方が良いかも知れません。
(実際のコードを見ていないので、影響度を読み切れません)


> 今3案で迷っている参考にしたかったのです。
もしも戻り値の判定が不要なら、呼び出し側が
 Text1.Text = Foo(Text1.Text)
となるように実装しておいた方が、「TextBox の内容を書き換えようとしている」という
コードの意図を読み取りやすいと思います;今回の案件に使えるかどうかは別ですが。


> 案3.子関数を修正する(これが本当は一番いい気がするのですが、今回は一番影響があるのでやりたくない上の意向)
具体的には、どのような影響が想定されていますか?
禁止されるだけの正当な理由があるのなら、これを修正案に含めるわけにはいかないと思います。


> 案1.既存の子関数をコピってTextBox用の子関数を別途作る。
それは「ByVal As TextBox」を受け取るプロシージャを作る、という意味でしょうか。
(この場合には、ByRef にする必要は無いでしょうから)

悪くは無いと思いますが、TextBox 以外(MaskEdBox など)を使っているところが出てくると、
さらに追加の処理が必要になってくるのが難点ですね。


> 案2.10箇所に私が考えたようなString型に一度セットしてから引数で渡し、戻った値をまたTextBoxにセットする。
それは、
 s = Text1.Text
 If MOJISET(s) = 0 Then
  Text1.Text = s
 End If
のようなコードでしょうか。

プロシージャの実装に手を入れられないのであれば、その修正も已む無しですが、
呼び出し側の意図が分かりにくいため、プロジェクトの規模が大きい場合には、
数ヵ月後に、別の担当者が誤って「再修正」してしまう危険性もありそうです。

引用返信 編集キー/
■47459 / inTopicNo.5)  Re[3]: VB6の参照渡し
□投稿者/ ななし (17回)-(2010/03/03(Wed) 09:33:02)
No47441 (tonton さん) に返信

私は案2が一番自然で素直で普通だと思います。
案1や案3とか、魔界の仮面弁士さんのMODE1から3でも、呼び出し側がMOJISET(TEXTBOX.Text)となっているとだめなことにはかわりないですし。
引用返信 編集キー/
■47465 / inTopicNo.6)  Re[4]: VB6の参照渡し
□投稿者/ 魔界の仮面弁士 (1524回)-(2010/03/03(Wed) 12:06:31)
No47459 (ななし さん) に返信
>> 案3.子関数を修正する(これが本当は一番いい気がするのですが、今回は一番影響があるのでやりたくない上の意向)
> 具体的には、どのような影響が想定されていますか?
> 禁止されるだけの正当な理由があるのなら、これを修正案に含めるわけにはいかないと思います。
できれば修正したい所だとは思いますが、もし、既存関数の手直しは
行わないと判断された場合でも、せめて、関数宣言部の
 MOJISET(moji)

 MOJISET(ByRef moji)
に修正する事を追加提案しておくというのは如何でしょうか。
(DefStr の可能性もゼロでは無いので、型指定についてはとりあえず保留)


今回のように型の指定さえ行われないような現場では、そもそも ByVal/ByRef の記載が
行われない事が非常に多いため、引数の入出力方向は不明瞭のまま開発されがちですが、
意図的に ByRef が埋め込まれていれば、そこに「出力引数」という意味を持たせられるため、
同様のコーディングが再発してしまう可能性を、僅かに減らせるかも知れません。

また、ByVal/ByRef を把握していない開発者に対しても、普段見慣れないキーワードが
含まれていれば、「ByRef って何だっけ?」という思考を与える切っ掛けにできるかも。


> 私は案2が一番自然で素直で普通だと思います。
その対応方法を他のメンバーにも周知徹底させておかないと、後々、
同じ問題が発生してしまい、泥縄になりかねないという懸念はありますが、
十分に啓蒙・教育できる場合においては、私も 案2 で良いと思います。


> 魔界の仮面弁士さんのMODE1から3でも
MODE3 は無かったと思いますが、MODE1/2 は冗長なので、普段は私も使いません。
(そもそも、出力引数は基本的に使わない派です)

Let/Set を区別できない言語(JScript等)と連携する ActiveX コンポーネントを
扱うような場合には、Property Let の引数処理時に、IsObject による判定が
必要になる事がごく稀にありましたが…今回のようなケースでは使うのは微妙ですね。


> 呼び出し側がMOJISET(TEXTBOX.Text)となっているとだめなことにはかわりないですし。
そうなんですよね。。。

しかも VB.NET だと、上記でプロパティ値が書き換え可能であるが故なのか、
開発者によっては、それがバグだと直感的に理解できない事もあるようで。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -