none
Shadows に関する不可解な現象 RRS feed

  • 質問

  • Visual Studio 2008 Standar の Visual Basic

    Visual Basic 2010 Exprss

    Visual Studio Express 2012 for Windows Desktop の Visual Basic

    で起きている問題なのですが ( OS は Windows7 Professional 64 bit )、

    Module Module1
        Sub Main()
            Dim d As New Derived()
            Dim s As String
    
            s = d.Test()
            Console.WriteLine(s)
    
            ' ↓なぜかビルドエラーにならず引数なしの Base.Test() が呼び出されるが、戻り値は明らかにおかしい。
            ' ( 引数を "n" とすると、文字列 "Derived.Test()" の n 番目の文字を返しているようだ。)
            s = d.Test("1")
            Console.WriteLine(s)
    
            ' ↓数字に変換できない文字を渡すと InvalidCastException が発生する。
            s = d.Test("A")
            Console.WriteLine(s)
    
            ' ↓こちらはビルドエラーになる。
            'd.Test("1")
        End Sub
    End Module
    
    Public Class Base
        Public Function Test() As String
            Return "Base.Test()"
        End Function
    
        Public Function Test(ByVal s As String) As String
            Return "Base.Test(ByVal s As String):" & s
        End Function
    End Class
    
    Public Class Derived
        Inherits Base
    
        Public Shadows Function Test() As String
            Return "Derived.Test()"
        End Function
    End Class

    のようなプログラムで、

    s = d.Test("1") はビルドエラーになるはずだと思っているのですが、ビルドエラーにならず、実行すると "e" と出力されます。

    また、s = d.Test("A") では InvalidCastException が発生します。

    これは Visual Basic のバグでしょうか?

    もし、これが仕様であるなら、s = d.Test("1") ではビルドエラーにならず、d.Test("1") だけだとビルドエラーになるのはどうしてでしょうか?

    どなたか何か情報をお持ちの方いらっしゃいましたら回答をお願い致します。

    2013年9月25日 13:11

回答

  • s = d.Test("1") はビルドエラーになるはずだと思っているのですが、ビルドエラーにならず、実行すると "e" と出力されます。

    また、s = d.Test("A") では InvalidCastException が発生します。

    これは Visual Basic のバグでしょうか?

    バグかどうかはわかりませんが、メカニズムはこうだと予想されます。

    d.Test で引数なしのメソッドを呼び出し、String 型のオブジェクトを得て、そのオブジェクトに対して (1) を実行しています。
    String 型は配列のように扱え、s(1) だと s という String 型変数の 2 番目の文字を Char 型として返します。
    Char 型は String 型に変換可能なので、2 番目の文字 'e' が、文字列 "e" になるのでしょう。
    "A" がエラーになるのは、String(Integer) の引数の型に合わないからでしょうね。

    こういった暗黙な変換でわかりづらい現象を避けるには「Option Strict On」としていただく方が堅いでしょう。

    もし、これが仕様であるなら、s = d.Test("1") ではビルドエラーにならず、d.Test("1") だけだとビルドエラーになるのはどうしてでしょうか?

    どなたか何か情報をお持ちの方いらっしゃいましたら回答をお願い致します。

    s(1) と書いて、代入先がない場合がエラーになるのと同じ理由でしょう。
    意味的には「s = d.Test」と「s(1)」を二行にわたって書いたことと同じ扱いです。

    2013年9月25日 13:40
    モデレータ

すべての返信

  • s = d.Test("1") はビルドエラーになるはずだと思っているのですが、ビルドエラーにならず、実行すると "e" と出力されます。

    また、s = d.Test("A") では InvalidCastException が発生します。

    これは Visual Basic のバグでしょうか?

    バグかどうかはわかりませんが、メカニズムはこうだと予想されます。

    d.Test で引数なしのメソッドを呼び出し、String 型のオブジェクトを得て、そのオブジェクトに対して (1) を実行しています。
    String 型は配列のように扱え、s(1) だと s という String 型変数の 2 番目の文字を Char 型として返します。
    Char 型は String 型に変換可能なので、2 番目の文字 'e' が、文字列 "e" になるのでしょう。
    "A" がエラーになるのは、String(Integer) の引数の型に合わないからでしょうね。

    こういった暗黙な変換でわかりづらい現象を避けるには「Option Strict On」としていただく方が堅いでしょう。

    もし、これが仕様であるなら、s = d.Test("1") ではビルドエラーにならず、d.Test("1") だけだとビルドエラーになるのはどうしてでしょうか?

    どなたか何か情報をお持ちの方いらっしゃいましたら回答をお願い致します。

    s(1) と書いて、代入先がない場合がエラーになるのと同じ理由でしょう。
    意味的には「s = d.Test」と「s(1)」を二行にわたって書いたことと同じ扱いです。

    2013年9月25日 13:40
    モデレータ
  • Azuleanさん、早速の回答ありがとうございます。

    なるほど、そういうことでしたか。s = d.Test("1") の ("1") は引数として解釈されていたんじゃなかったんですね。

    ("1") は引数だと思い込んでしまっていました・・・。( 思い込みって恐ろしい・・・。)

    >バグかどうかはわかりませんが、・・・

    いやいや、明らかにバグではありませんよね。(^^;

    適切で明快な回答ありがとうございました。

    2013年9月25日 14:17