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

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

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

Re[3]: Subの呼び出しで添え字を付けるとどうなりますか?


(過去ログ 161 を表示中)

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

■93148 / inTopicNo.1)  Subの呼び出しで添え字を付けるとどうなりますか?
  
□投稿者/ 番長 (1回)-(2019/11/24(Sun) 15:00:53)

分類:[.NET 全般] 

ForループでSubルーチン処理をする際、
以下のように書くこともできますが、

For j As Integer = 1 To 1000

     Call Test(j)

Next j


Sub Test(j%)


End Sub


     Call Test(j)のところを

     Call Test(j%)としても実行することができます。

今までどちらでも同じだと思っていたのですが、
Sub Test(j%)
の中でエラーが頻発したので、
Call Test(j%)
と書いていたところを

Call Test(j)
に修正するとエラーが出なくなりました。

%を付けるとどういう処理になっていますか?



引用返信 編集キー/
■93149 / inTopicNo.2)  Re[1]: Subの呼び出しで添え字を付けるとどうなりますか?
□投稿者/ 大統領 (1回)-(2019/11/24(Sun) 15:33:09)
> Sub Test(j%)
> の中でエラーが頻発したので、

どんなエラーが発生していたのでしょうか?
%はIntegerを表す添え字なので、
強制的にIntegerに変換されることによって不都合が発生したのでは?
引用返信 編集キー/
■93152 / inTopicNo.3)  Re[2]: Subの呼び出しで添え字を付けるとどうなりますか?
□投稿者/ 番長 (2回)-(2019/11/24(Sun) 16:03:05)
ありがとうございます。
つまりCintと同じ意味でしょうか?
自分でもなぜエラーがなくなったのかよく分からないのですが・・・
もしかしてbyrefがbyvalに切り替わりますか?

引用返信 編集キー/
■93153 / inTopicNo.4)  Re[3]: Subの呼び出しで添え字を付けるとどうなりますか?
□投稿者/ キングダム (47回)-(2019/11/24(Sun) 16:38:24)
なんていうエラーが出てたのですか?
引用返信 編集キー/
■93163 / inTopicNo.5)  Re[3]: Subの呼び出しで添え字を付けるとどうなりますか?
□投稿者/ 魔界の仮面弁士 (2497回)-(2019/11/25(Mon) 11:06:48)
No93152 (番長 さん) に返信
>>> %を付けるとどういう処理になっていますか?
> つまりCintと同じ意味でしょうか?

いいえ、違います。

CInt は実行時に型変換させるためのものですが、
型文字(型宣言文字)はコンパイル時の型を明示するものです。

https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/language-features/data-types/type-characters?WT.mc_id=DT-MVP-8907



たとえば下記を Option Infer On モードでコンパイルした場合、
変数 a と c は As Integer になりますし、
変数 b と d は As Long としてコンパイルされます。

'右辺のリテラルに、型文字を指定
Dim a = 1%
Dim b = 2&
Dim c = 3I
Dim d = 4L


---
下記の場合、「リテラル 1」「リテラル 2」は Integer 型ですが、
「変数 a」は Integer 型で、「変数 b」は Long 型としてコンパイルされます。
「変数 c」は UInteger 型で、「変数 d」は ULong 型です。

Dim a% = 1
Dim b& = 2
Dim c = 3UI
Dim d = 4UL


'-----
Dim a As Integer = 123
MsgBox(a)  'これは OK
MsgBox(a%)  'これは OK
'MsgBox(a&)  'コンパイル エラー:BC30277「型文字 '&' が宣言されたデータ型 'Integer' と一致しません。」


'-----
Dim a& = 0
MsgBox(a) 'これは OK
'MsgBox(a%) 'コンパイル エラー:BC30277「型文字 '%' が宣言されたデータ型 'Long' と一致しません。」
MsgBox(a&)  'これは OK



型文字の意味は、変数であろうと定数であろうとメソッドの引数であろうと同じことです。



> もしかしてbyrefがbyvalに切り替わりますか?


ByRef で宣言された仮引数が、実引数次第では ByVal 相当として
呼び出されることはありますが…それと型宣言文字 % の件はまったく別です。


ところで、仮引数と実引数、ってわかりますか?

No93148 で提示頂いたコードで言えば、
呼ばれる側となる『Sub Test(j%)』あるいは『Sub Test(j As Integer)』の j が「仮引数(parameter、パラメーター、かりひきすう)」で、
呼び出す側となる『Call Test(j%)』あるいは『Call Test(j)』の j が「実引数(argument、アーギュメント、じつひきすう)」です。

VB.NET の場合、ByRef や ByVal は仮引数で定義されるもので、実引数では指定できません。
(VBA では、特定の条件を満たした場合に限り、実引数側に ByVal をつけることも可能ですが)


そして ByRef な仮引数がある場合、受け渡される実引数は
『同じデータ型の変数』であることが前提となります。



たとえば下記の ByRef 引数の呼び出しは、『正しくないコード』の例です。
(「間違ったコード」ではなく、『正しくないコード』です)

'Option Strict On
'Option Strict Off
Module Module1
 Sub Main()
  Dim v1 As Integer = 123
  Dim v2 As Integer = 456
  Call ByRefTest(v1%) '変数を渡す(ByRef 動作を期待)
  Call ByRefTest((v2%)) '式を渡す(ByVal 相当の結果)
  Call MsgBox(v1)
  Call MsgBox(v2)
 End Sub
 Sub ByRefTest(ByRef x As Long)
  x = 987
 End Sub
End Module


上記を Option Strict On モードでコンパイルした場合、エラー BC32029 となります。
「Call ByRefTest(v1%)」として呼び出している部分を、
「Call ByRefTest(v1)」や「ByRefTest(v1)」や「ByRefTest(v1%)」と書いても同じエラーです。


しかし Option Strict Off モードの場合には、エラー無く処理されます。
Option Strict Off の時には、上記の ByRefTest の呼び出し部が
下記の処理に置きかえられてコンパイルされるためです。

Sub Main()
 Dim v1 As Integer = 123
 Dim v2 As Integer = 456

 'Call ByRefTest(v1%) '←この行は、コンパイル時に下記↓のように書き換わる
 Dim num& = v1 '★1 拡大変換で正しい型の変数が用意される
 Call ByRefTest(num&) '★2 正しい型を使って呼び出される
 v1 = CInt(num) '★2 縮小変換で元の変数に書き戻され、出力引数として動作する

 'Call ByRefTest((v2%)) '←この行は、コンパイル時に下記↓のように書き換わる
 num = v2 '★3 拡大変換
 Call ByRefTest(num&) '★4 正しい型を使って呼び出される
 '「変数」ではなく「式」が渡されていたので、変数 v2 への書き戻しは行われない

 Call MsgBox(v1) '987 に置き換わっている
 Call MsgBox(v2) '456 のまま
End Sub



質問内容から想像すると、現状、このあたりのデータ型の違いをきちんと理解しきれていないように思えます。
プロジェクトのプロパティの[コンパイル]タブを開き、コンパイルオプションの
 Option Explicit → On
 Option Strict → On
を設定した状態で、正しくコンパイルされるコードを書くことを目指してみてください。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -