none
言語仕様(2.0、3.0)の違いによるエラーでしょうか? RRS feed

  • 質問

  • C#2.0では、正常にコンパイルできていたのですがC#3.0ではコンパイルエラーになってしまいます。

    コードの下線でエラーになります。「ref またはout引数は、割り当て可能な変数でなければなりません」

    言語仕様の変更によるものでしょうか? 言語仕様のどこに記述がありますか?

    実際はどっちが正しいのでしょうか?

    知ってる方、宜しくお願いいたします。

    class test
    
    {
    
      void proc1(ref short s)
    
      {
    
      }
    
      void proc2(short s)
    
      {
    
        short s = 0;
    
        proc1(ref (short) s);
    
      }
    
    }
    
    

     

    2010年6月30日 6:46

回答

  • 回答ではないですがお邪魔させていただきます。
    proc2 の引数sと変数sが重複するのでそこは回避して動作確認しました。
    で、ちょっと実験、、、
    proc1(ref (short)ss);
    proc1(ref ss++);
    でも同じエラーになります。
    ss++ は明確に値型なのでこれは当然。

    これを Visual Studio 2003 の環境でビルドすると
    「ref または out 引数は左辺値でなければなりません。」
    というエラーになります。

    さらに実験、、、
    int a=1, b=2, c=4;
    (int)a = b + c;
    と書くと、2003 ではエラーになりませんが
    2008 では「代入式の左辺には変数、プロパティ、またはインデクサを指定してください。」というエラーになりました。

    これらのことから
    “昔は (int)a みたいな書き方しても変数参照(左辺値)とみなしてくれたんだ”
    というところは見えてくるような気がします。

    これが C# 2.0 と 3.0 の違いかどうかについては、
    双方の言語仕様の該当しそうな箇所を見ましたが違いは解りませんでした。
    言語仕様とコンパイラ仕様が別物だとして、
    C# 3.0 ではいろいろ書き方が増えたため
    チェックを厳しくしないとコンパイラが対応できなかったのではないか
    と憶測しています。

    • 編集済み anningo 2010年6月30日 9:50 間違い部分取り消し(取り消し線)
    • 回答の候補に設定 山本春海 2010年7月5日 2:41
    • 回答としてマーク ビッグフィールド 2010年7月5日 3:07
    2010年6月30日 8:47
  • こんにちは。

    #proc2メソッドの「short s = 0;」の行はケアレスミスですよね、きっと

    「(short) s」は式です。

    ref は変数の格納場所を渡す文法です。(まあ、アドレスですね)

    なのでエラーになるのが正しいと思います。

    C#コンパイラはバージョンが上がるたびに重箱の隅な穴をふさいできているので、それで修正されたのだと思います。


    2010年6月30日 9:34
  • プロジェクトプロパティのアプリケーションタブに「対象のフレームワーク」があり、そこでアプリケーションが使用する

    FrameWorkのバージョンが選択できます。

    試しに、提示されているコードを2.0と3.0の2つで試してみましたが、両方ともCS1510コンパイルエラーが発生します。

    VS2008 では、対象のフレームワークのバージョンに関わらずコンパイラは C# 3.0 の物を使用します。
    2010年6月30日 9:39

すべての返信

  • proc2メソッドの引数としてshort型で渡ってきている値渡し「s」を、同じshort型にキャストしているのは何故ですか?

    通常であれば、以下でいいかと思われます。

    	class test
    	{
      	public void proc1(ref short s)
      	{
      	}
    
      	public void proc2(short s)
      	{
        	proc1(ref s);
      	}
    	}

    2010年6月30日 7:38
  • 回答ありがとうございます。意見はごもっともですが

    (まともなプログラムでないのは重々承知です。)

    今回は、言語仕様の確認の質問になっております。

    2010年6月30日 7:46
  • 回答ではないですがお邪魔させていただきます。
    proc2 の引数sと変数sが重複するのでそこは回避して動作確認しました。
    で、ちょっと実験、、、
    proc1(ref (short)ss);
    proc1(ref ss++);
    でも同じエラーになります。
    ss++ は明確に値型なのでこれは当然。

    これを Visual Studio 2003 の環境でビルドすると
    「ref または out 引数は左辺値でなければなりません。」
    というエラーになります。

    さらに実験、、、
    int a=1, b=2, c=4;
    (int)a = b + c;
    と書くと、2003 ではエラーになりませんが
    2008 では「代入式の左辺には変数、プロパティ、またはインデクサを指定してください。」というエラーになりました。

    これらのことから
    “昔は (int)a みたいな書き方しても変数参照(左辺値)とみなしてくれたんだ”
    というところは見えてくるような気がします。

    これが C# 2.0 と 3.0 の違いかどうかについては、
    双方の言語仕様の該当しそうな箇所を見ましたが違いは解りませんでした。
    言語仕様とコンパイラ仕様が別物だとして、
    C# 3.0 ではいろいろ書き方が増えたため
    チェックを厳しくしないとコンパイラが対応できなかったのではないか
    と憶測しています。

    • 編集済み anningo 2010年6月30日 9:50 間違い部分取り消し(取り消し線)
    • 回答の候補に設定 山本春海 2010年7月5日 2:41
    • 回答としてマーク ビッグフィールド 2010年7月5日 3:07
    2010年6月30日 8:47
  • プロジェクトプロパティのアプリケーションタブに「対象のフレームワーク」があり、そこでアプリケーションが使用する

    FrameWorkのバージョンが選択できます。

    試しに、提示されているコードを2.0と3.0の2つで試してみましたが、両方ともCS1510コンパイルエラーが発生します。

    実際にVS2005で2.0のみの環境では試していませんのでなんとも言えません。

    CA系の警告ならプロジェクトの設定を疑うのですが・・・

     

    なお、anningoさんの仰る様に、同様に、キャストにも以下が言えます。

    proc1(ref s);

    sは、メソッドの引数が値渡しで受け取っているので、メソッド内での実体をもつのでOK

    proc1(ref (short) s);

    short型にキャストされたsはどこにも代入されておらず、参照渡し元の実体が定義されていないことになりNG

    short hoge = (short)s;
    proc1(ref hoge);
    short型にキャストされたsは、一旦hogeという実体に代入され、参照渡し元の実体が定義されていることになりOK

    2010年6月30日 9:11
  • こんにちは。

    #proc2メソッドの「short s = 0;」の行はケアレスミスですよね、きっと

    「(short) s」は式です。

    ref は変数の格納場所を渡す文法です。(まあ、アドレスですね)

    なのでエラーになるのが正しいと思います。

    C#コンパイラはバージョンが上がるたびに重箱の隅な穴をふさいできているので、それで修正されたのだと思います。


    2010年6月30日 9:34
  • プロジェクトプロパティのアプリケーションタブに「対象のフレームワーク」があり、そこでアプリケーションが使用する

    FrameWorkのバージョンが選択できます。

    試しに、提示されているコードを2.0と3.0の2つで試してみましたが、両方ともCS1510コンパイルエラーが発生します。

    VS2008 では、対象のフレームワークのバージョンに関わらずコンパイラは C# 3.0 の物を使用します。
    2010年6月30日 9:39
  • VS2008 では、対象のフレームワークのバージョンに関わらずコンパイラは C# 3.0 の物を使用します。
    そうでしたか、では意味のない検証になっちゃいましたね、申し訳ありません(汗
    2010年7月1日 0:34