VB.Netクラスの共有メソッドの使い方とエラーの回避方法

このQ&Aのポイント
  • VB.Netでクラスの共有メソッドを作成する方法と、エラーの回避方法について教えてください。
  • ファイルの保存と読み込みに関する共有メソッドの作成方法を詳しく教えてください。
  • エラー「正規の式は評価されません」および「'ByRef' パラメータのオブジェクトの値を縮小変換できませんでした」とは何ですか?どのように回避すればよいですか?
回答を見る
  • ベストアンサー

VB.Net: クラスの共有メソッドの作り方?

あと3日でVB.Net学習2ヶ月目という初学者です。 Sub Main() のみで基本事項の確認のみをしてきました。 ですから、フォーム、レポート、データベース、WEB関連の知識は完全にゼロ。 さて、その基本演習も最終段階に突入。 いよいよクラスです。 ' ============================== ' クラスプログラミング; 演習3 ' ============================== Module theClass   Sub Main()     Dim T1 As New TEST1     T1.Member1 = "T1.Member1"     T1.Member2 = "T1.Member2"     T1.BSave("D:\Temp\T1.bin", DirectCast(T1, Object)) <--- ?1     T1.Member1 = "AAA"     T1.Member2 = "BBB"     Debug.Print(T1.Member1)     Debug.Print(T1.Member2)     T1.BLoad("D:\Temp\T1.bin", T1) <--- ?2     If T1 IsNot Nothing Then       Debug.Print(T1.Member1)       Debug.Print(T1.Member2)     Else       Message("T1.bin は読み込めませんでした。")     End If   End Sub End Module ?1=インスタンスを経由する共有メンバ、・・・へのアクセスです。正規の式は評価されません。 ?2=Option strict on では、'ByRef' パラメータのオブジェクトの値を・・・縮小変換できませんでした。 Public Shared Sub BSave(ByVal aPath As String, ByVal aObject As Object)   Try     Using fs As New FileStream(aPath, FileMode.Create, FileAccess.Write)       Dim bf As New BinaryFormatter       bf.Serialize(fs, aObject)       fs.Close()     End Using   Catch ex As IOException     MsgBox(ex.Message & "(BSave)", MsgBoxStyle.Exclamation, "エラー:")   End Try End Sub Public Sub BLoad(ByVal aPath As String, ByRef aObject As Object)   If File.Exists(aPath) Then     Try       Using fs As New FileStream(aPath, FileMode.Open, FileAccess.Read)         Dim bf As New BinaryFormatter         aObject = bf.Deserialize(fs)         fs.Close()       End Using     Catch ex As IOException       MsgBox(ex.Message & "(BLoad)", MsgBoxStyle.Exclamation, "エラー:")     End Try   End If End Sub 非共有の BSaveメソッドとBLoadメソッドのパラメータはファイルパスだけ。 共有メソッドの場合は、「何を」というのが必要かと思って2つ目のパラメータを追加。 もって、構造体の BSave と BLoad とに援用するテストをしたいと思っています。 し、しかし、上述の2つのエラーを前にどうしてよいか皆目わかりません。 >そのエラーを回避、もしくは発生させないためには次のように改造したらよい! そういう回答等をお願いします。

noname#140971
noname#140971

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

?1: Sharedなメソッドを呼び出すのですから, インスタンス.メソッド の形ではなく 型.メソッド の形になります。 つまり,今回の場合は, TEST1.BSave("D:\Temp\T1.bin", T1) のように書く必要があります。 各クラスはSystem.Objectを暗黙の内に継承しているため,Objectへのキャストを書く必要はありません。 ?2: 第2引数には,デシリアライズされたオブジェクトを代入するための,Object型の変数を指定します。 つまり, Dim obj As Object = Nothing T1.BLoad("D:\Temp\T1.bin", obj) Dim T2 As TEST1 = TryCast(obj, TEST1) If T2 IsNot Nothing Then のような形になります。 ところで,Sharedの修飾がどう考えても逆に思えますが。 <Serializable> _ Public Class Test  Public Sub Save (ByVal fileName As String)   '自分自身をfileNameに保存する  End Sub  Public Shared Function Load (ByVal fileName As String) As Test   'fileNameから読み込む  End Function End Class のような形になるのが自然だと思います。 これだと, Dim t As Test として, ' 保存 t.Save("D:\Temp\t1.bin") '読み込み t = Test.Load("D:\Temp\t1.bin") のように書くことになります。

noname#140971
質問者

お礼

>共有メソッドはクラス名でアクセスする! 読み飛ばしていました。 >ところで,Sharedの修飾がどう考えても逆に思えますが。 BLOAD を共有にするのを忘れていました。 無用の混乱を与えてすみません! ですから、以下の修正で成功しました。 本当にありがとうございました。 ' ============================== ' クラスプログラミング; 演習3 ' ============================== Module theClass   Sub Main()     Dim T1 As New TEST1     Dim obj As Object = Nothing     T1.Member1 = "T1.Member1"     T1.Member2 = "T1.Member2"     TEST1.BSave("D:\Temp\T1.bin", T1)     T1.Member1 = "AAA"     T1.Member2 = "BBB"     Debug.Print(T1.Member1)     Debug.Print(T1.Member2)     TEST1.BLoad("D:\Temp\T1.bin", obj)     If T1 IsNot Nothing Then       Debug.Print(TryCast(obj, TEST1).Member1)       Debug.Print(TryCast(obj, TEST1).Member2)     Else       Message("T1.bin は読み込めませんでした。")     End If   End Sub End Module Public Sub BSave (ByVal fileName As String)   '自分自身をfileNameに保存する End Sub これは非共有のメソッドとして書きました。 ただ、非共有と共有の共存については未だテストしていません。 本日が、クラス演習の初日なのでよく個も全体もわかっていません。 本当にありがとうございました。

関連するQ&A

  • クラス

    VB.NET 学習58日目という初学者です。 未だ、Sub Main() でシコシコと基本事項の確認中です。 やっと構造体の演習を昨日から。 案の定、わからないことに遭遇しました。 ' ============================== ' TEST1、TEST2 の BSave、BLoad ' ============================== Module theTEST1   Sub Main()     ' -----------------------     ' TEST1 の BSave、BLoad     ' -----------------------     Dim T1 As New TEST1     T1.Member1 = "T1.Member1"     T1.Member2 = "T1.Member2"     BSave(T1, "D:\Temp\T1.BIN")     T1.Member1 = "AAA"     T1.Member2 = "BBB"     Debug.Print(T1.Member1)     Debug.Print(T1.Member2)     T1 = CType(BLoad("D:\Temp\T3.BIN"), TEST1)     If T1.Member1 <> Nothing Then ' Null エラーが回避できない!       Debug.Print(T1.Member1)       Debug.Print(T1.Member2)     Else       Message("")     End If     ' -----------------------     ' TEST2 の BSave、BLoad     ' -----------------------     Dim T2 As TEST2     T2.Member1 = "T2.Member1"     T2.Member2 = "T2.Member2"     BSave(T2, "D:\Temp\T2.BIN")     T2.Member1 = "AAA"     T2.Member2 = "BBB"     Debug.Print(T2.Member1)     Debug.Print(T2.Member2)     T2 = CType(BLoad("D:\Temp\T3.BIN"), TEST2)     If T2.Member1 <> Nothing Then       Debug.Print(T2.Member1)       Debug.Print(T2.Member2)     Else       Message("")     End If   End Sub End Module Function BLoad(ByVal aPath As String) As Object   If File.Exists(aPath) Then     Try       Using fs As New FileStream(aPath, FileMode.Open, FileAccess.Read)         Dim bf As New BinaryFormatter         Dim aObject As Object = bf.Deserialize(fs)         fs.Close()         Return aObject       End Using     Catch ex As IOException       MsgBox(ex.Message & "(BLoad)", , "エラー:")       Return Nothing     End Try   Else     Return Nothing   End If End Function T1 はクラスライブラリで定義。 T2 は構造体。 構造体の場合は、Nothing でチェックできました。 しかし、クラスライブラリの場合はチェックできません。 このエラーの考え方と処し方を教えてください。 構造体とクラスライブラリは表向きは同じようなもの。 ですから、どちらにも通用する BSave、BLoad 関数を作成使用としたわけです。 宜しくお願いします。

  • VB2008: 構造体に関するMSDNの解釈について!

    ' ================== ' 構造体変数の代入 ' ================== Module theTEST   Private Structure TEST4     Dim MembersCount As Integer     Dim Member1 As String     Dim Member2 As String   End Structure   Sub Main()     Dim T4_1 As TEST4     Dim T4_2 As TEST4     T4_1.MembersCount = 1     T4_1.Member1 = "T4_1:Member1"     T4_1.Member2 = "T4_1:Member2"     T4_2 = T4_1     Debug.Print(T4_2.MembersCount.ToString)     Debug.Print(T4_2.Member1)     Debug.Print(T4_2.Member2)   End Sub End Module [イミディエイト ウインドウ] 1 T4_1:Member1 T4_1:Member2 >構造体の要素が文字列型 (String) やオブジェクト型 (Object) などの参照型である場合は、データへのポインタがコピーされます。 (http://msdn.microsoft.com/ja-jp/library/18ytyskd(VS.80).aspx) このMSDNライブラリの説明によると、 [イミディエイト ウインドウ] 0 T4_1:Member1 T4_1:Member2 という結果を得るというのが私の予測。 もしかしたら、MSDNライブラリの説明の舌足らず。 >構造体の要素が値型であらば値がコピーされますが、文字列型 (String) やオブジェクト型 (Object) などの参照型である場合は、データへのポインタがコピーされます。 ということでしょうか?

  • VB.NETのデリゲートについて

    VB.NETのデリゲートについて質問です。 以下のプログラムなのですが、 デリゲート型をインスタンス化しているところで、コンストラクタにパラメータを渡していますが、 そのコンストラクタはどこに定義されているのでしょうか。 (AddressOf t1.Ohayou)というパラメータが渡されていますが、このパラメータを受け取っているコンストラクタがどれなのかが分かりません。 ご教示よろしくお願いいたします。 Delegate Sub Myprint(ByVal s As String) Module Module1 Sub Main() Dim t1 As Test1 = New Test1() Dim t2 As TEst2 = New Test2() Dim d As Myprint = New Myprint(AddressOf t1.Ohayou) d.Invoke("VB太郎") d = New Myprint(AddressOf t2.Konbanwa) d.Invoke("VB太郎") End Sub End Module Class Test1 Sub Ohayou(ByVal s As String) Console.WriteLine("おはようございます。{0}です。", s) End Sub End Class Class Test2 Sub Konbanwa(ByVal s As String) Console.WriteLine("こんばんわ。{0}です。", s) End Sub End Class

  • ASP.NET OleDbConnectionが定義がされていません

    ACCESS2003 で 以下のサンプルを実行すると OleDbConnectionが定義がされていません。 というエラーが発生していて対処方法をしらべ てもわかりませんでした。 何方かご教授ください。よろしくお願いいたします。 Public Sub InsertRow(ByVal connectionString As String, _ ByVal insertSQL As String) Using connection As New OleDbConnection(connectionString) Dim command As New OleDbCommand(insertSQL) command.Connection = connection Try connection.Open() command.ExecuteNonQuery() Catch ex As Exception Console.WriteLine(ex.Message) End Try End Using End Sub 以下のOleDbConnectionオブジェクトの作成は行いました。 http://www.atmarkit.co.jp/fdotnet/aspexp/aspexp03/aspexp03_01.html

  • VB2008: ファイルから1行づつ読み込む関数のバグの修正方法?

    ' ========================================== ' 全ての行を読み込んで "" 行以外を出力する ' ========================================== Module theGrap   Sub Main()     Dim iNow As Integer = 0     Dim iNext As Integer = 0     Dim aLine As String = ""     Do       iNow = iNext       aLine = FGets("D:\Temp\Test4.txt", iNow, iNext)       If aLine = "" Then Continue Do       Debug.Print(aLine)     Loop Until iNext = -1   End Sub End Module [イミディエイト ウインドウ] 123あいうえお90 123かきくけこ90 123さしすせそ90 と、成功しています。 ' -------------- ' 行末まで読む ' -------------- Do   fs.Seek(iNowPosition, SeekOrigin.Begin)   fs.Read(aBuf, 0, 2)   aChar = ec.GetString(aBuf).Substring(0, 1)   If aChar <> Chr(13) Then     aChars &= aChar   Else     iNowPosition = iNowPosition - 1     Exit Do   End If   iNowPosition += txt.LenB(aChar) Loop While iNowPosition < fs.Length And (aChar <> Chr(13) Or aChar <> Chr(10)) しかし、実は、FGets 関数では1文字づつ読み込んでいます。 そこで、StreamReader で一行を読み込むように修正。 [イミディエイト ウインドウ] 123?????90 123?????90 123?????90 すると見事に化けてしまいました。 化けること自体は理解できるのですが、化けを修正する術がわかりません。 Function FGetl(ByVal aFile As String, _         ByVal iNowPosition As Integer, _         ByRef iNextPosition As Integer) As String   Dim aBuf(1) As Byte   Dim aChars As String = ""   iNextPosition = -1   If File.Exists(aFile) Then     Try       Using fs As FileStream = New FileStream(aFile, FileMode.Open, FileAccess.Read)         Dim sr As StreamReader         Dim ec As Encoding = Encoding.Default         fs.Seek(iNowPosition, SeekOrigin.Begin)         sr = New StreamReader(fs)         aChars = sr.ReadLine         iNowPosition += txt.LenB(aChars)         iNextPosition = NextPosition(fs, iNowPosition)         fs.Close()         Return aChars       End Using     Catch ex As IOException       MsgBox(ex.Message & "(FGets)", MsgBoxStyle.Exclamation, "エラー:")       Return ""     End Try   Else     Return ""   End If End Function 文字の化けを修正する方法を教えて頂ければ幸いです。

  • VB6で作成した自作DLLをVB.NETで呼び出し例外発生時に参照渡しの引数に値を設定する方法

    VB6で作成した自作のDLLをVB.NET2005で作成したEXEから呼び出した際に、DLLメソッドの正常・異常終了に関わらず第2引数の戻り値に第1引数の値を設定したいと考えていますが旨くいきません。 何かよい方法はないでしょうか? 以下、簡単なサンプルです。 =========================== VB6 DLL =========================== Public Sub getDataForTest(ByVal strIn As String, ByRef strOut As String) Dim intData As Integer 'strInの値をstrOutに代入 strOut = strIn 'strInの値を1で割り算 intData = CInt(strIn) / 1 End Sub =============================================================== =================== DLL呼び出し正常パターン =================== Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim objCom As New Project1.Class1 Dim strRet As String = "" Try Call objCom.getDataForTest("1", strRet) Catch ex As Exception MsgBox(ex.Message) Finally MsgBox(strRet) ←←← 1が表示される  End Try End Sub =============================================================== =================== DLL呼び出し異常パターン =================== Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim objCom As New Project1.Class1 Dim strRet As String = "" Try Call objCom.getDataForTest("A", strRet) Catch ex As Exception MsgBox(ex.Message) Finally MsgBox(strRet) ←←← この時にAを表示したいがstrRetが空  End Try End Sub ===============================================================

  • VB2008: 独自例外とは?

    独自例外の確認ための質問をします。 独自例外の発生をキャッチして表示する術がわからなくて苦肉の策でエラートラップを利用。 しかし、こういう事であれば何も独自例外を設定する必要がありません。 と思ったり、「スルーだからテストに<0除算>を選んだのが悪いのか?」と考えたり。 ともかく、判っているのか判っていないのかが判らない状態に陥っています。 そういうことで、独自例外について少し教えて頂ければ幸いです。 ' ============================== ' クラスプログラミング; 演習2 ' ============================== Module theClass   Sub Main()     On Error GoTo Error_Main     Dim T1 As New TEST1     Debug.Print(T1.MembersLengthAverage.ToString) Exit_Main:     Exit Sub Error_Main:     ErrorMsg(Err.Description & "(Main)")     Resume Exit_Main   End Sub End Module ' ================================================================== ' クラス TEST1 ' ================================================================== <Serializable()> Public Class TEST1   Private _MemberCount As Integer   Private _Member1 As String   Private _Member2 As String    ReadOnly Property MembersLengthAverage() As Integer     Get       If _MemberCount <> 0 Then         Return (_Member1.Length + _Member2.Length) \ _MemberCount       Else         Throw New System.Exception("TEST1: 除算エラーが発生しました。" )       End If     End Get   End Property   Public Sub New()     _Member1 = ""     _Member2 = ""   End Sub End Class

  • VB2008: クラスの既定のプロパティの活用イメージに関して?

    本日でちょうど60日目というVB.NET 初学者です。 未だ Sub Main() での基本事項の確認に終始しています。 3日まえより基本事項の最終課題にクラスを選んで挑戦中。 ですから、少し、質問しなければ判らないことだらけです。 今回の質問は、<既定のプロパティ>についてです。 ' ========================== ' クラス; 既定のプロパティ ' ========================== Module theDefault   Sub Main()     Dim T1 As New TEST1     T1(0) = "Kenji"     Debug.Print(T1(0))     Debug.Print(T1.MembersFriends(0))   End Sub End Module このように、確かに、既定のプロパティは省略した構文で書けるので便利。 それはわかります。 が、問題は、その具体的な活用イメージがサッパリです。 「例えば、こういうケースに使うととっても便利」という具体例があれば教えてください。

  • VB2010 SQLのUPDATE文エラー

    VB2010とAccess2007で使用しています データを日付順に連番を付けるコードを作成したのですが『UPDATE文構文エラーです』等のエラーが発生します? ご教授お願いします。 Private Sub Button連番_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button連番.Click Dim DT As New DataTable Try Using OleCn As New OleDbConnection(mdbPath) Dim SQL As String = "" SQL = "SELECT * FROM tableA ORDER BY 依頼日" Using DA As System.Data.OleDb.OleDbDataAdapter = _ New System.Data.OleDb.OleDbDataAdapter(SQL, OleCn) DT.Clear() DA.Fill(DT) End Using End Using Using OleCn As New OleDbConnection(mdbPath) Dim SQL As String = "" SQL = "UPDATE tableA SET No = @no WHERE 登録ID_Export = @登録ID" Dim OleCmd As New OleDbCommand(SQL) OleCmd.Connection = OleCn OleCn.Open() OleCmd.Parameters.Add("@no", OleDbType.Integer) OleCmd.Parameters.Add("@登録ID", OleDbType.Integer) For i As Integer = 1 To DT.Rows.Count OleCmd.Parameters("@no").Value = i OleCmd.Parameters("@登録ID").Value = CInt(DT.Rows(i)("登録ID_Export").ToString) OleCmd.ExecuteNonQuery() Next i OleCmd.Dispose() OleCn.Dispose() End Using Catch ex As Exception MessageBox.Show(ex.ToString, "例外発生") Exit Sub End Try MsgBox("ok") End Sub

  • VB2010でCSV取込

    VB2010とAccessを使用しています。 あるCSVファイルからACCESSへデータ取り込みをしようとして CSVをデータテーブルに代入するコードを考えているのですが 下記のコードでは『FROM句』のエラーのようでうまく作動しません? ご教授お願いします。 Private Sub ToolMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolMenu.Click Dim OFD As New OpenFileDialog OFD.FileName = "" OFD.InitialDirectory = "\\10.20.100.35\data\LOG\" OFD.Filter = "CSVファイル(*.csv)|*.csv|すべてファイル(*.*)|*.*" OFD.FilterIndex = 1 OFD.Title = "取り込むCSVファイルを選択してください" OFD.RestoreDirectory = True OFD.CheckFileExists = True OFD.CheckPathExists = True If OFD.ShowDialog() = DialogResult.OK Then Try Dim DT As New DataTable '===============CSVからクエリ=============== Using OleCn As New System.Data.OleDb.OleDbConnection Dim CSVFileName As String = System.IO.Path.Combine(OFD.InitialDirectory, "aaa.csv") OleCn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & OFD.InitialDirectory & _ ";Extended Properties=""Text;HDR=YES;IMEX=1;FMT=Delimited""" Dim SQL As String = "" SQL = "SELECT * FROM " + CSVFileName Using DA As System.Data.OleDb.OleDbDataAdapter = _ New System.Data.OleDb.OleDbDataAdapter(SQL, OleCn) DT.Clear() DA.Fill(DT) End Using End Using Catch ex As Exception MessageBox.Show(ex.ToString, "例外発生") Exit Sub End Try End If End Sub

専門家に質問してみよう