2009-07-31 11 views
2

次のシナリオを検討してください:.NETのラッパータイプ:構造体またはクラス?

int Caller1<T>(T t) where T : IInterface {...} 
T Caller2<T>() where T : IInterface {...} 

class Wrappee // doesn't implement IInterface, but could 

??? Wrapper : IInterface { 
    private readonly Wrappee _wrappee; 

    // methods call _wrappee's methods 
} 

さて、structclassの間で選択するための一般的なアドバイスは、「あなたが参照セマンティクスのために値のセマンティクスとclassが必要な場合structを使用する」です。必要なセマンティクスは「Wrappeeへの参照」です。しかし、我々はまだWrapper構造体を作ることができるようです:その値をコピーするのは同じですWrappeeのコピーと同じであり、コピーは同じオブジェクトへの参照を持つでしょう!オーバーヘッドは低く、scalar replacementはローカル変数の値を0に減らすことができます。 _wrappeeで突然変異法を呼び出すことは大丈夫です。

何か不足していますか?代わりにWrapperをクラスにする良い理由はありますか?

呼び出し側がジェネリックでない場合は、1つがあります:

int Caller(IInterface t) {...} 

この場合Wrapperはボクシングを避けるために、クラスでなければなりません。

ハスケルを知っている人のための備考:最も近い.NETアナログをnewtypeに見つけることを試みています。

更新:最初のケースでボクシングがない場合は、Professional .NET 2.0 GenericsPeter Ritchie on MSDN forumsを参照してください。

+0

一般的なタイプのパラメータとして構造体を使用すると、ボクシングの必要性に違いが生じるのはなぜですか? –

+0

アップデートを参照してください。 –

答えて

2

あなたのクラス/構造体は、あなたが呼び出したメソッド(Caller1とCaller2が何をするかを表示していない)によって内部的に格納または渡されることがよくあり、その場合はおそらくボックス化されます。おそらくあなたが予想したよりも頻繁に。したがって、構造体がより効率的になることを証明できない限り、クラスに気を配り、固執しないでください。

さらに、構造体はデータ型のようなものを表現しない限り、しばしば戸惑うことがあるので、クラスを選択すると、将来の異なる性質の議論が妨げられる可能性があります。

ただし、パフォーマンスがの場合は実際にであり、インスタンスがジェネリック型制約を持つパラメータとして渡され、インターフェイス型フィールドまたはコレクションに格納されないことが保証できる場合は、現在の構造体のインライン展開あなたのラッパー構造体がほとんど最適化されるので、.NETランタイムによってより効率的になります。しかし、それは多くのifsです。

0

あなたはデータだけでなく、動作をカプセル化しているので、私はクラスと言っています。

4

はい、ボクシングを避けるために、IInterface変数を使用してラッパーにアクセスするので、それはクラスでなければなりません。

編集:Wrapperとして型付けされた変数でラッパーにアクセスし、IInterfaceメソッドではなくWrapperメソッドにアクセスすると、構造体は正常です。

+0

私は 'IInterface'変数でアクセスしませんが、' IInterface'から派生するように制約されたジェネリックパラメータです。アップデートを参照してください。 –

+0

つまり、呼び出しコードは次のようになります。 'Wrapper y = Caller2(); return Caller1(y); ' –

関連する問題