none
型の定義方法について RRS feed

  • 質問

  • いつもお世話になっております。

    環境:xp,vs2008

    型の定義について悩んでいます。
    プラットフォーム毎で型を変えたい場合、以下の様なコードみたいにしたいのですがこれではコンパイルできません。
    勿論、各ネームスペースに入った所で個別に同様のプリプロセッサディレクティブ記述するればコンパイル自体は通るのですがこれだとコード変更時の対応が多くなってしまいます。
    出来れば、同じ内容を共通的に使用する方法があればお教えいただけませんでしょうか。
    リファレンスでは、ファイルまたはネームスペースのスコープで適用されるみたいに書いているようにみえるのですが駄目でした。

    以上、よろしくお願いいたします。

    //-------------------
    //VariantType1.cs
    //-------------------
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace VariantTypeTest {
    #if OS_A
        using DataSize1 = System.UInt64;
        using DataSize2 = System.UInt64;
    #else
        using DataSize1 = System.UInt32;
        using DataSize2 = System.UInt64;
    #endif
       
        partial class VariantType {
            public DataSize1 SizeA1 = 0;
            public DataSize2 SizeA2 = 0;
        }
    }

    //-------------------
    //VariantType2.cs
    //-------------------
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace VariantTypeTest {
        partial class VariantType {
            public DataSize1 SizeB1 = 0;
            public DataSize2 SizeB2 = 0;
        }
    }

    2009年10月5日 6:21

回答

  • で、後は元のコードがC++からの移植なのですがtypedef unsigned char u8;の様なものはusing u8 = System.Byte;の記述で対応できるのですがこれを全ソースに記述するのはちょっと手間もそうですが保守の面でも手間が増えそうなので、共通的な部分の宣言・定義は共通化したいのですが、Cであればtypedefの記述したファイルをincludeで対応できますが、C#ではこのようなものはどう対応すればよいんでしょうか?
    typedef の概念は C# にはありません。(あったとしても、ファイル単位の using エイリアスまで)

    C# と C++ は異なる言語ですから、そういった古く分かりづらいコードは捨てるか、書き直しましょう。
    C# で今後も保守していくのであれば、その言語にあった実装にしていくことが保守性を高めることになると思います。
    現状の C++ のコードをなんとか C# で動かそうと逃げる行為は、どんな手を使っても保守という面では負けるでしょう。

    Windows 上に限っても良いのであれば、C++/CLI で流用部分をライブラリとしてラップして、新規部分を C# で書くという構成もありでしょう。
    ただ、Xbox 等を視野に入れるのであれば、やっぱり書き直した方が良いと思います。
    (Win32 等を対象とした .NET Framework でできることが、Xbox ではできないということもあるため)


    # u8 は想像できなくもないですが、ある型が実際にはどんな型が何かとかいちいち調べるようなことは結構手間です。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク chaf_dev 2009年10月5日 14:10
    • 編集済み AzuleanMVP, Moderator 2009年10月5日 14:18 言葉が足りていなかった箇所を補完(ライブラリして→ライブラリとしてラップして)
    2009年10月5日 13:38
    モデレータ

すべての返信

  • 32bit / 64bitの切り替えに限定されますがIntPtr構造体ではだめですか?
    数値ではないので数値演算はできませんが。
    2009年10月5日 8:03
  • 32bit / 64bitの切り替えに限定されますがIntPtr構造体ではだめですか?
    数値ではないので数値演算はできませんが。
    すいません、質問の意図が少しずれてしまっていたので少し補足致します。

    #if OS_A
        using DataSize1 = System.UInt64;
        using DataSize2 = System.UInt64;
    #else
        using DataSize1 = System.UInt32;
        using DataSize2 = System.UInt64;
    #endif

    の記述を各ソースに記述する必要があるのが問題なので、型の定義自体は想定した動作を行えています。

    • 編集済み chaf_dev 2009年10月5日 11:09 応答ミス
    2009年10月5日 8:22
  • ※※※再考した結果、
    例えば”値型を自前で定義する”あるいは”プリコンパイラによるマクロ展開”といった類の
    解決策を求められている質問内容であると判断しました。
    過去の返信の編集により、意味のつながらない返信になってしまったこともあり、
    返信を削除いたします。
    • 編集済み anningo 2009年10月5日 13:39 ※※※参照
    2009年10月5日 10:59
  • まぁ一般論としての回答で、chaf_devさん以外の人がこのスレッドを閲覧したときに参考になれば、という思いもあります。
    なのでchaf_devさんが他人の書いたコードを再利用するとかそういう事情はあまり気にしていません。

    .NETというプラットフォームからある程度独立した環境でありながら、32bit / 64bitの違いが1万ステップ全体に及ぶというのでしたら…ご愁傷様としか言えませんね。
    普通、IOやImage(画像ファイル)なんかはプラットフォーム依存しないはずなんじゃ…64bit版Windowsだと見れない画像ファイルとかあるんですか?
    # そういえばWICコーデックが対応してなくて見れない画像がありましたね。

    C#にはプリプロセッサというものが最小限しか用意されていないので、無理矢理やろうとしたら型を作ってしまうしかないです。
        struct Int3264 {
    #if !OS_A
            public Int32 Value;
    #else
            public Int64 Value;
    #endif
        }
    とか。でもそれならIntPtrと変わらない気がします。
    2009年10月5日 11:21
  • まぁ一般論としての回答で、chaf_devさん以外の人がこのスレッドを閲覧したときに参考になれば、という思いもあります。
    なのでchaf_devさんが他人の書いたコードを再利用するとかそういう事情はあまり気にしていません。

    .NETというプラットフォームからある程度独立した環境でありながら、32bit / 64bitの違いが1万ステップ全体に及ぶというのでしたら…ご愁傷様としか言えませんね。
    普通、IOやImage(画像ファイル)なんかはプラットフォーム依存しないはずなんじゃ…64bit版Windowsだと見れない画像ファイルとかあるんですか?
    # そういえばWICコーデックが対応してなくて見れない画像がありましたね。

    C#にはプリプロセッサというものが最小限しか用意されていないので、無理矢理やろうとしたら型を作ってしまうしかないです。
        struct Int3264 {
    #if !OS_A
            public Int32 Value;
    #else
            public Int64 Value;
    #endif
        }
    とか。でもそれならIntPtrと変わらない気がします。
    依存についてですが、.netとは少し違いますがxnaライブラリではプラットフォームの依存があるようです。
    例えば、Texture2DはXbox 360, Windows XP SP2、Windows Vista, Zune のプラットフォームがサポート範囲ですがそのメソッドのFromFileは Windows XP SP2、Windows Vista になっています。

    上記例で言えば以下のような感じで書けると良いんじゃないかと思ったのですが、どうもエイリアスの中身を見られるっぽいので結局キャストを要求されますね・・。
    //駄目な例
    namespace ns_test{
    #if (XBOX||ZUNE)
    class TextureEx : Texture2D{
        public TextureEx(GraphicsDevice graphicsDevice, int w, int h):base(graphicsDevice,w,h){}
        public static Texture2D FromFile (GraphicsDevice graphicsDevice, Stream Stream){
            Texture2D t = new Texture2D(graphicsDevice, 0,0);
            //...steamからごにょごにょとか色々
            return t;
        }
    }//end of TextureEx
    #else
    using TextureEx = Texture2D;
    #endif

    class Test{
        Test(GraphicsDevice g){
            using(FileStream fs = new FileStream("t.bmp", FileMode.Open, FileAccess.Read)){
                t = TextureEx.FromFile(g, fs);
                fs.Close();
            }
        }
    }//end of Test
    }//end of namespace ns_test


    という事で、結局クラスの部分の置き換えは地道に各プラットフォーム毎に切り替える事で対応するしかなさそうですね。
    クラスの数がそこまで多いわけではないのでスクラッチするというのでがんばる事にしようと思います。

    で、後は元のコードがC++からの移植なのですがtypedef unsigned char u8;の様なものはusing u8 = System.Byte;の記述で対応できるのですがこれを全ソースに記述するのはちょっと手間もそうですが保守の面でも手間が増えそうなので、共通的な部分の宣言・定義は共通化したいのですが、Cであればtypedefの記述したファイルをincludeで対応できますが、C#ではこのようなものはどう対応すればよいんでしょうか?
    2009年10月5日 12:50
  • で、後は元のコードがC++からの移植なのですがtypedef unsigned char u8;の様なものはusing u8 = System.Byte;の記述で対応できるのですがこれを全ソースに記述するのはちょっと手間もそうですが保守の面でも手間が増えそうなので、共通的な部分の宣言・定義は共通化したいのですが、Cであればtypedefの記述したファイルをincludeで対応できますが、C#ではこのようなものはどう対応すればよいんでしょうか?
    typedef の概念は C# にはありません。(あったとしても、ファイル単位の using エイリアスまで)

    C# と C++ は異なる言語ですから、そういった古く分かりづらいコードは捨てるか、書き直しましょう。
    C# で今後も保守していくのであれば、その言語にあった実装にしていくことが保守性を高めることになると思います。
    現状の C++ のコードをなんとか C# で動かそうと逃げる行為は、どんな手を使っても保守という面では負けるでしょう。

    Windows 上に限っても良いのであれば、C++/CLI で流用部分をライブラリとしてラップして、新規部分を C# で書くという構成もありでしょう。
    ただ、Xbox 等を視野に入れるのであれば、やっぱり書き直した方が良いと思います。
    (Win32 等を対象とした .NET Framework でできることが、Xbox ではできないということもあるため)


    # u8 は想像できなくもないですが、ある型が実際にはどんな型が何かとかいちいち調べるようなことは結構手間です。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク chaf_dev 2009年10月5日 14:10
    • 編集済み AzuleanMVP, Moderator 2009年10月5日 14:18 言葉が足りていなかった箇所を補完(ライブラリして→ライブラリとしてラップして)
    2009年10月5日 13:38
    モデレータ
  • typedef の概念は C# にはありません。(あったとしても、ファイル単位の using エイリアスまで)

    C# と C++ は異なる言語ですから、そういった古く分かりづらいコードは捨てるか、書き直しましょう。
    C# で今後も保守していくのであれば、その言語にあった実装にしていくことが保守性を高めることになると思います。
    現状の C++ のコードをなんとか C# で動かそうと逃げる行為は、どんな手を使っても保守という面では負けるでしょう。

    Windows 上に限っても良いのであれば、C++/CLI で流用部分をライブラリして、新規部分を C# で書くという構成もありでしょう。
    ただ、Xbox 等を視野に入れるのであれば、やっぱり書き直した方が良いと思います。
    (Win32 等を対象とした .NET Framework でできることが、Xbox ではできないということもあるため)


    # u8 は想像できなくもないですが、ある型が実際にはどんな型が何かとかいちいち調べるようなことは結構手間です。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    ご回答ありがとうございます。

    このポストの結果として書き直すという事を結論としたいと思います。
    ただ、以下の様な型をファイル単位(正確には、ファイル単位のネームスペース単位)でコピペで記述するのは決して保守性が高いコードとは考えにくいですし、かといって既にある型を自前で記述するのもどうかと思います。
    //---typedef start---
    using i8 = System.SByte;
    ...
    using u64 = System.UInt64;
    //---typedef end---
    ネームスペース全体共通で適応してくれればこれだけで済むのですが、他に方法がなさそうなので自前で型を定義するか、型の置換を行う事にしようと思います。

    #確かに、u8とかは分かりにくい気がしますが、そこの部分は私が書いたコードではないのでご容赦ください。
    #また、IDE前提の編集であれば全てのケースではありませんが調べたいワードにマウスカーソルを合わせるか[Ctrl + K] + I でクイックヒントを表示できるので許容範囲なんではないかと思っています。



    2009年10月5日 14:58
  • ただ、以下の様な型をファイル単位(正確には、ファイル単位のネームスペース単位)でコピペで記述するのは決して保守性が高いコードとは考えにくいですし、かといって既にある型を自前で記述するのもどうかと思います。
    //---typedef start---
    using i8 = System.SByte;
    ...
    using u64 = System.UInt64;
    //---typedef end---
    C# での開発においては、エイリアスを多用すること自体をまず疑うべきです。
    安易な「省略」や「別名の定義」はコードを分かりにくくする可能性が高いでしょう。
    それ故に、楽にできないように設計されているのかも知れません。
    (これは裏付け取っていません。C# の言語仕様の設計思想などは興味があればお調べください)

    また、全てのファイルに using エイリアスを書きたいということがほとんどないと思っています。

    # 流用元のコードのコーディングスタイルの問題を指摘しても何も得られませんので、C# で生産性が悪いと主張されている点のみを対象としています。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年10月5日 16:15
    モデレータ