5

4.0 DLRで遊んでいて、動的とオブジェクトを比較していて、これに出くわしました。

コード:

object x = 10;
            Console.WriteLine("x = {0} and is a {1}.\n", x, x.GetType());
            x = (int)x + 3;
            Console.WriteLine("x = {0} and is a {1}.\n", x, x.GetType());
            x = x + "a";
            Console.WriteLine("x = {0} and is a {1}.\n", x, x.GetType());

結果:

x = 10であり、System.Int32です。

x = 13であり、System.Int32です。

x = 13aであり、System.Stringです。

私には、オブジェクトが実行時にオブジェクトを型に適合させようとしているように見えます(動的)。ただし、3行目のintにxをキャストしないと、静的型付けに適していると思われるコンパイラー領域が得られます。しかし、xに「a」を追加すると、文字列として認識されるようになります。

私は何が欠けていますか?

4

7 に答える 7

6

演算子が文字列に適用されると、(型のインスタンスではないオペランドでメソッドを+呼び出すことによって)自動変換を行うという事実を見逃しています。.ToString()String

于 2013-02-19T20:45:38.720 に答える
4

C#言語仕様から:

7.8.4加算演算子

一方または両方のオペランドが文字列型の場合、事前定義された加算演算子は、オペランドの文字列表現を連結します。

  • 文字列の連結:

    string operator +(string x, string y);
    string operator +(string x, object y);
    string operator +(object x, string y);
    

    二項+演算子のこれらのオーバーロードは、文字列の連結を実行します。文字列連結のオペランドが。の場合null、空の文字列に置き換えられます。それ以外の場合、文字列以外の引数は、ToStringオブジェクト型から継承された仮想メソッドを呼び出すことにより、文字列表現に変換されます。ToStringを返す場合null、空の文字列に置き換えられます。

于 2013-02-19T20:50:30.517 に答える
2

変数のタイプ(であるobject)とそれが参照するオブジェクトのタイプには違いがあることに注意してください。

System.Stringタイプは、値の1つとしてを受け入れ、それobjectに対して自動を実行する演算子を定義するため、最後の変換が許可ToString()されます。

ランタイムまたは動的操作に面白いビジネスはありません。

于 2013-02-19T20:48:15.337 に答える
1

私には、オブジェクトが実行時にオブジェクトを型に適合させようとしているように見えます(動的)。

実際にはそうではありません。それobjectは、あらゆるタイプのオブジェクトを格納する.NETの機能を実行するだけです。

であるためにdynamicは、変数は、たとえば、キャストなしで何でも呼び出すことができるようにする必要があります

dynamic x = "hello";
dynamic y = x.Substring(0, 2); // The compiler does not complain

上記のトリックを「プレーン」objectで実行しようとすると、コンパイラから怒りのメッセージが表示されます。ただし、の使用はdynamic、実行時まで不平を延期します。実行時、その時点で発生するか、まったく発生しない可能性があります。

しかし、xに「a」を追加すると、文字列として認識されるようになります。

これは、コンパイラが行う「魔法のかけら」です。コンパイラは、をobject持っていることを認識しToString、自動的に呼び出しを挿入します。

于 2013-02-19T20:46:51.340 に答える
1

C#のすべての型はオブジェクト型から派生しているため、任意の型を格納できます。

object x = 10;
x = x + "a";

それはコンパイラが実際に行うことです。objectを持っているので.ToString()、を使用する+と、コンパイラが自動的に呼び出します。

このILコードを見ても;

  .locals init ([0] object x)
  IL_0000:  nop
  IL_0001:  ldc.i4.s   10
  IL_0003:  box        [mscorlib]System.Int32
  IL_0008:  stloc.0
  IL_0009:  ldloc.0
  IL_000a:  ldstr      "a"
  IL_000f:  call       string [mscorlib]System.String::Concat(object,
                                                              object)

String.Concatこのメソッドの戻り値はstring、値の表現です。

C#5.0仕様から:

  • 文字列の連結:

    string operator +(string x, string y);
    string operator +(string x, object y);
    string operator +(object x, string y);
    

    二項+演算子のこれらのオーバーロードは、文字列の連結を実行します。文字列連結のオペランドが。の場合null、空の文字列に置き換えられます。それ以外の場合、文字列以外の引数は、ToStringオブジェクト型から継承された仮想メソッドを呼び出すことにより、文字列表現に変換されます。ToStringを返す場合null、空の文字列に置き換えられます。

于 2013-02-19T20:52:40.243 に答える
0

「オブジェクト」から継承されたc#のすべてのデータ型。したがって、操作の基本的な動作は、演算子と他のオブジェクトによって異なります。

于 2013-02-19T20:50:03.723 に答える
0

C#のすべてはから継承しobjectます。int、、、stringなどcharはすべて行います。

これを行うとき:

object x = 10;

変数を作成し、xそれを整数値10に初期化します。値は、であり、オブジェクトに含まれているintだけです。boxed

xあなたがあなたとしてキャストするとき、intあなたはunboxingそれが実際のタイプになります。

ボクシングとアンボクシングについては、このガイドを確認してください

于 2013-02-19T20:46:21.913 に答える