2015-12-28 11 views
11

私は2つの質問があります。値型が参照型から継承するのはなぜですか?

  1. 私たちは、すべてのタイプが参照型であるObjectから派生知っているが。 タイプである - - 参照型Objectから継承intは、なぜ私の質問はありますか?これは可能ですか?パラメータとしてobjectを期待する機能するようにintを渡すときにintもし

  2. Objectに由来し、なぜ我々は、ボックスする必要がありますか?通常、参照型では、派生型のオブジェクトをパラメータとして渡して、基本型のオブジェクトを期待して機能させる必要があるときは、何も追加する必要はありません。なぜここのボックス?

この状況は、このタイプの階層がどのように設計されたかという問題のようです。

PS。私はthis関連の質問を見つけましたが、答えは現実的な洞察を与えません - ちょうど抽象的な箱について話しています。

+0

'すべての型はオブジェクトから派生しました。 '__は常に真です。 –

+2

[この他の質問](http://stackoverflow.com/questions/1682231/how-do-valuetypes-derive-from-object-referencetype-and-still-be- valuetypes)に対する受け入れられた回答は、はるかに関連しています –

+1

[すべてがオブジェクトから派生しているわけではありません](http://i1.blogs.msdn.com/b/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx) –

答えて

2

我々は、すべての型がObjectから派生知っています。これは参照型です。値型である - - 私の の質問は、なぜintで参照 型Objectから継承しますか?これは可能ですか?

System.Int32すべての構造体は、C#でそうであるように、System.ValueTypeに由来します。この継承チェーンは、他のstruct型では継承からあなたを禁止しているのと同じメカニズムで、コンパイラによって許可されています。共通言語ランタイム(CLR)は、System.ValueTypeから派生する型の特殊なセマンティクスを持っています。 System.ValueType自体は値型ではなく、すべての構造体の基本クラスを形成する参照型です。この継承階層は存在しますが、オブジェクトがメモリ内でどのようにレイアウトされるかについては何も保証する必要はありません。

なぜ、オブジェクトとして をパラメータとしてintを関数に渡す必要がありますか?通常の参照あなたは基本型の期待オブジェクトを関数のパラメータとして 派生型のオブジェクトを渡す必要があり、 で追加の何もする必要はありません。なぜここのボックス?任意のstructが最終的objectから派生したものの、それが実際に実行時で異なる扱いをされているので

。すべての構造体はデータのまとまりとして扱われ、.NETのすべての参照型にはメソッドテーブルポインタまたはシンクブロックインデックスはありません。追加データが実際に完全修飾objectタイプになるために、それに追加する必要があるためobjectを受け入れるメソッドに渡される任意の値型は、ボックス化されなければならない理由です。あなたがインターフェイスを実装した結果としてあなたstructに追加されたメソッドを呼び出したときにそれらがobject型として渡さしているときに値の型のみ箱入りされていない、彼らはまた、例えば、箱入りされています。その値の型は、呼び出す必要のあるメソッドへの実際のメソッドテーブルのポインタを取得するために、ボックス化する必要があります。

あなたは小さな例でそれを見ることができます(リリースモードでコンパイル)

void Main() 
{ 
    IFoo m = new M(); 
    m.X(); 
} 

public struct M : IFoo 
{ 
    public void X() { } 
} 

public interface IFoo 
{ 
    void X(); 
} 

には、次のILが得られます:

IL_0000: ldloca.s 00 
IL_0002: initobj  UserQuery.M 
IL_0008: ldloc.0  
IL_0009: box   UserQuery.M 
IL_000E: callvirt UserQuery+IFoo.X 
IL_0013: ret   
+0

@downvoter downvoteを説明してください –

+0

私たちはすべて持っています。すべての投稿は –

+0

@Henk私はdownvotesが説明される必要があるとは言いませんでした。 –

-1

値型はスタックに割り当てられたかにインラインで割り当てられているいずれか構造。参照型はヒープに割り当てられます。参照型と値型はどちらも、究極の基底クラスObjectから派生しています。 値型がオブジェクトのように動作する必要がある場合、値型を参照オブジェクトのように見せるラッパーがヒープに割り当てられ、値型の値がそのオブジェクトにコピーされます。ラッパーには、値タイプが入っていることがシステムに認識されるようにマークされています。このプロセスはボクシングと呼ばれ、逆のプロセスはアンボクシングと呼ばれます。ボクシングとアンボクシングでは、あらゆるタイプをオブジェクトとして扱うことができます。

3

ここでコンセプトを混同しないように注意する必要があります。

まず、サブタイプがあります。 intはサブタイプobjectです。サブタイプは基本的に、スーパータイプによって保証されている契約(例えば、「ToStringメソッドがあり、適切な文字列を返します。」)もサブタイプに対して保証されています。

次に、の継承がC#にあります。 C#では、継承

  1. はスーパータイプが提供するインタフェースは、サブタイプでも利用可能であり、あなたがオーバーライドしない場合

  2. は、デフォルトの実装、すなわちを提供することを確保することによって、サブタイプを作成します方法、あなたはスーパータイプの実装を取得します。これは基本的に便利な機能です。

基本的にすべてです

(C位でインタフェースの実装は、1を提供する別のサブタイプの機構、たとえばなく2であろう)。サブタイプ化または継承は、メモリレイアウト、値/参照型セマンティクスなどを保証しません。概念は直交しています。


"しかし、それは正しくありません、"あなたは言うかもしれません。 "object契約の一部は「参照型セマンティクス」です。これは、ボクシングが必要な場所です。値タイプのコンパイル時型が参照型(すなわち、object,ValueTypeまたはインタフェース)である場合はいつでも参照型セマンティクスをシミュレートします。

+0

「でもそれは正しいことではありません。オブジェクト契約の一部は「参照型セマンティクス」です。これはボクシングが必要なところです。値型のコンパイル時の型が参照型(オブジェクト、ValueType、インタフェースなど)の場合は常に参照型セマンティクスをシミュレートします。 " - しかし、通常は派生型のオブジェクトを渡すときに何もする必要はありません。基本的な型への参照を期待する関数へのパラメータですが、ここではボクシングが必要なので、これはある程度の奇妙な状況です –

+0

@ user200312:確かに、構造体とクラスの両方に共通の基底クラスを持っているので、コンパイラがすべての作業(自動ボクシングとアンボクシング)を行うので、私は喜んで支払う価格です。 – Heinzi

関連する問題