Option Strict Onでのデータの取り扱い

タグの編集
投稿者 hoido  (社会人) 投稿日時 2010/5/20 18:36:50
いつもお世話になっております。
早速ですが、ネットを見ているとOption Strict Onを推奨するとよく見かけます。
そこでOption Strict Onにしてみるとエラーが沢山!!
そこで質問なのですが、
For Each Row As DataRow In Table.Rows
    Sql = ""
    Select Case Row.RowState
      Case DataRowState.Modified
           Sql = "UPDATE tbl_Hisashi SET "
           Sql &= "生産順 = '" & Row("生産順") & "' "

For Each Row As DataRow In Table.Rows
    If IsDBNull(Row(0)) OrElse Row(0) = 0 Then Continue For
    If Row(0) <> c + 1 Then Continue For
などDataTableのRowのデータを使ったところがことごとく
”Option Strict On では、演算子 '&' に対して Object 型のオペランドを使用することはできません。”
等のエラーが発生しています。
やはり全部CIntやToString等を付けてエラーを回避するのが基本なのでしょうか。
それともOption Strict Offにしてしまっても良いものなのでしょうか。
現在動作自体問題なく動いてはいるのですが、基礎を身に着けたく質問させていただきました。
検索が下手で同じ内容の質問があるかも知れませんがご了承ください。
ご教授よろしくお願いいたします。
投稿者 (削除されました)  () 投稿日時 2010/5/20 19:28:58
(削除されました)
投稿者 葉月  (社会人) 投稿日時 2010/5/20 19:32:53
こんばんは。

業務やC#を使う予定があるなら、Option Strictは、Onにした方がいいと思います。
ただ、サンプルや趣味で作るプログラムもOnにするのはめんどくさいです。
デメリットも多いのでメリットとはいいませんが――
Option Strict Onを必ずした方がいいという意見は、
VBの自由度を損なっているように感じます。
Onにしなさいという意見もわかるので、反対意見ではないです。

本題に入ります。
Option Strict Onの場合は、自動で型の変換を行いません。
まずは参考URL(VB中学校の記事)を見てください。

恐らく、エラー内容は
Dim 変数名 As Objectで宣言していませんでしょうか?
そうなら、適切な型を宣言した方がいいと思います。

>>>検索が下手で同じ内容の質問があるかも知れませんがご了承ください。
マルチポスト(他の方が運営している掲示板でもで同じ質問をしている)していますでしょうか?
当てはまるなら、他に質問している掲示板と連動するように結果や途中経過を報告するようにしてください。
(マルチポストを禁止にしている場所もあります)
以上のことを行わずに、ひな形の質問をするのは、運営や回答者の方に失礼な行為となるのでご注意ください。 
投稿者 hoido  (社会人) 投稿日時 2010/5/21 00:19:12
葉月様返答ありがとうございます。

>>>マルチポスト(他の方が運営している掲示板でもで同じ質問をしている)していますでしょうか?
こちらのサイトのみに質問させていただいております。

>>>Dim 変数名 As Objectで宣言していませんでしょうか?
質問の仕方が悪かったのですが、Tableにはこちらのサイトを参考にさせていただき
  Dim Table As DataTable = DirectCast(DataGridView1.DataSource, DataTable)
のようにTableの値を設定しています。
また、DataGridViewには下記のようにSQLServerからの読み込んだデータをセットしております。
  Dim Cn As SqlConnection = New SqlConnection(SelectServer)
  Dim SQLCm As SqlCommand = Cn.CreateCommand
  Dim Tbale As DataTable = New DataTable
  Dim Sql As String
  sql=・・・・・
  SQLCm.CommandText = Sql
  Adapter.Fill(dt)
  Me.DataGriView.DataSource = Table
それなのでObject型で宣言している場所がありません。
SqlServerから読み込んだ場合すべてObject型として認識されるのでしょうか?
今一度お願いいたします。
投稿者 葉月  (社会人) 投稿日時 2010/5/21 01:12:45
こんばんは。

Dim Table As DataTable = DirectCast(DataGridView1.DataSource, DataTable)


DataTable型にキャスト(型変換)しています。
プログラミングになれると、自然にキャストする癖がつきます。
プログラムの量が増えると、暗黙の型変換が原因で実行時に想定していた動きに
ならないケースがあります。
型変換によるミスは、見つかりにくい厄介な問題に進展するケースがあります。

そういう経緯があり、Option StrictはOnにした方がいいよという方が出てきます。
私の意見は既に述べているので省略します。

回答としては、hoidoさんが述べていますが――
「CIntやToString等を付けてエラーを回避するのが基本なのでしょうか」
になります。
それから、CTypeによるキャストも覚えておくといいですよ。

Option Strict Offのままでもいいと思いますが、
気付いたところはキャストした方がいいですね。
最後に関連するURLを載せますので、よかったら見てください。

>>>SqlServerから読み込んだ場合すべてObject型として認識されるのでしょうか?
私の推測が外しているので、Object型で宣言はしていません。
' この場合はDataTable型になります。 
Dim Table As DataTable
投稿者 hoido  (社会人) 投稿日時 2010/5/21 07:46:04
葉月様回答ありがとうございました。
詳しい説明、また参考サイト大変参考になりました。
基本Option Strict Onでプログラムしその他問題ないレベルまで出来た時点でOffにする方向で進めてみようと思います。
本当にありがとうございました。
投稿者 よねKEN  (社会人) 投稿日時 2010/5/21 11:32:04
> CIntやToString等を付けてエラーを回避するのが基本なのでしょうか

はい、適切な型変換を行うのが基本です。ただし、どのように扱うべきかは、
変換元になる内容に応じて手段を選択してください。
(なんとなくエラーが回避できるから、CIntやToStringを使っておけばいい、
 のような判断にだけはならないようにしてください。)

以前、別のサイトで型変換について話題になったことがありますが、
参考になるかと思いますので、URLを記載しておきます。

「キャストについて」
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=47815&forum=7
投稿者 るしぇ  (社会人) 投稿日時 2010/5/21 11:39:36
> ネットを見ているとOption Strict Onを推奨するとよく見かけます。
ボクも推奨派。自分の指示できるプロジェクトでは強制してます。
実行時には遅延バインディングとなり、結局キャストされるので、プログラマが
意識して型変換のコードを書いて事前バインディングにしておく方が、バグの
早期発見につながります。
どんなデータが扱われているのか把握していれば、Option Strict On で
全て書けるようになると思います。

DataSet、DataTable、DataRowあたりの話だと、NULL 判定が入ってきたりで、
単純にキャストというようには行かなくなる方が多いのでは?むしろ入力チェック
に近いようなカスタマイズが必要になるので、データ型毎にサブプロシージャ
を用意している事が多いかもしれません。(引数で NULL 許可だとか、書式とかを指定)
チェックする項目は限られますからね。

単純にキャストに近いというか、入力した時点でチェックされていいなら
「型付き~」というのがあります。
ウィザードを使うので、ボクはちょっと敬遠気味の技術ですが、使った人の意見
もWEB上に転がってますので検索してみてください。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=37730&forum=7
http://social.msdn.microsoft.com/Forums/ja-JP/vsgeneralja/thread/d2a02163-f768-47fb-8c74-1d51dd5ea975

>>>SqlServerから読み込んだ場合すべてObject型として認識されるのでしょうか?
[DataRow.Item プロパティ]
http://msdn.microsoft.com/ja-jp/library/5akhx035.aspx
元々は、フィールドの型は厳密に定義されてなかったんです。
プロパティが Object 型を返します。
数値型でも、文字列型でも、日付型でも入りますからね。いちいちオブジェクトの
方で指定しなかった。
ちょっと古い考え方だと、データ型毎にオーバーロードで別プロパティを用意して
って発想になったんじゃないかな?
Excel でもセルの値とか Object で何でも処理します的なコードが書けます。
何でも.Select みたいな。型チェックとかは呼び出し側でそれぞれ作って
くださいよって設計だったんです。
それでも型指定が重要ですよーって意識が高まってきて、簡単に型指定できるような
技術が伴って色々な機能が追加されてます。

[余談]LINQ あたりの話から匿名型ってのも出てきてて、型の推論てのもあって。。。
http://msdn.microsoft.com/ja-jp/library/cc468406(VS.90).aspx
またややこしくなった気がするのはボクだけ?orz
投稿者 hoido  (社会人) 投稿日時 2010/5/21 17:14:53
よねKEN様、るしぇ様回答ありがとうございます。
今実際修正をかけていたのですが、型指定するとだんだんコードが長くなり、見づらくなってきて・・・
でも遅延バインディングになっちゃうし でも・・・でも初めに基本を身に着けておかないと・・・でも動いちゃうし
といった具合でなかなか進んでいない状態でした
ただやはり皆様の意見を聞かせていただき重要度を再認識させてもらいました。
ありがとうございました。
投稿者 るしぇ  (社会人) 投稿日時 2010/5/21 17:48:49
>今実際修正をかけていたのですが、型指定するとだんだんコードが長くなり、見づらくなってきて・・・
関数化してまとめられない?
一回、別の変数に受けてみるとか?

    Private Sub test()
        Dim Table As DataTable
        Dim c As Integer
        Dim intData As Integer

        For Each Row As DataRow In Table.Rows
            intData = MyCInt(Row(0))
            If intData = 0 Then Continue For
            If intData <> c + 1 Then Continue For
        Next
    End Sub

    Public Function MyCInt(ByVal Value As ObjectAs Integer
        'この条件は仕様に応じて変更してください 
        If IsDBNull(Value) Then
            Return 0
        Else
            Return CInt(Value)
        End If
    End Function
投稿者 hoido  (社会人) 投稿日時 2010/5/21 17:55:13
るしぇ様返答ありがとうございます。
>>>関数化してまとめられない?
何事も勉強!!
早速トライしてみたいと思います!!!
投稿者 葉月  (社会人) 投稿日時 2010/5/22 13:59:27
最初に、他の方が提示してくれた説明やリンク、勉強になりました。
ありがとうございます。

本題に入ります。
今回のテーマに外れますが、hoidoさんの書き込みで気になった点がありました。
質問内容を理解しないと書けないはずのコードがあったためです。

見覚えのない記述があったら、一度は調べることをお勧めします。
調べてわからなかったら、不明点を質問すれば誰かしら答えてくれます。
使えりゃいいやって感じで、私はかなりいい加減な性格ですが、
そんな私でも不明点を少しずつ無くすようにはしています。
この点を疎かにすると、差がつくのでご注意ください。

もし、既に業務を行っているなら、
時間を取って不明瞭な点を整理した方がいいかも知れません。
それから、現場の方が暇しているのを見計らって聞いてみてください。

>>>指定するとだんだんコードが長くなり、見づらくなってきて・・・
それがわかっているなら焦ることはありません。
今後、多くのサンプルを見たり書いていくうちに、読みにくくしている原因に気づきます。
よくある意見の一つで、プログラムを読む読む書く書くが上達の早道です。


最後に、前回の私のカキコで、伝え方が悪かった個所がありました。

>>>Option StrictはOnにした方がいいよという方が出てきます。
「Option StrictはOnにした方がいいよという方がいます」と書きたかったのですが、
表現が変わっていました。
もし、読んでて不快に思った方がいましたら申し訳ないです。