9

以下で何が起こっていますか?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class DotNetPad
{
    public static void Main(string[] args)
    {
        int i = 10;
        string k = "Test";
        Console.WriteLine(i+k);
        Console.WriteLine(k+i);
    }
}

iどちらの場合も文字列に変換されています。私は、演算子の優先順位(この例ではその多くを示していませんが)と評価の方向性の考え方と混同しています。評価は左から右へ、またはその逆で行われる場合があります。表現がどのように評価されるかについての科学を正確に知りません...

i上記の例で文字列に変換され、実際にはコンパイルエラーが発生しないのはなぜですか?

4

4 に答える 4

23

C#仕様から-セクション7.7.4追加演算子:

文字列の連結

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

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

于 2012-05-02T13:58:25.863 に答える
18

演算子の優先順位と評価の方向性の考え方と混同しています。

いいえ、違います。これはよく混乱しますが、整数が文字列に変換されるかどうか、または整数を文字列に追加することが合法である理由の問題には、優先順位も評価の順序も関係しないため、混乱することはありません。 。

あなたが混乱していると主張する点で最初にあなたを混乱させないために、規則は非常に単純です:

  • 式は、演算子の優先順位と結合性に従って括弧で囲まれています。
  • 部分式は左から右の順序で評価されます。

それを正しくするために知っておく必要があるのはそれだけです。Q()がセッター付きのインデクサーを持つオブジェクトを返し、他のメソッドはすべて整数を返すとします。

Q()[R()] = A() * B() + C() / D();

これは、優先順位と結合性に従って括弧で囲まれています。

Q()[R()] = ( ( A() * B() ) + ( C() / D() ) );

そして今、すべての部分式は左から右に評価されます。それ自体が部分式を持っている部分式を含む、すべての部分式。したがって、これはプログラムと同等です。

var q = Q(); 
var r = R(); 
var a = A(); 
var b = B(); 
var t1 = a * b; 
var c = C();
var d = D();
var t2 = c / d;
var t3 = t1 + t2;

最後に、qのインデックスセッターがインデックスrと値t3で呼び出されます。

左側のすべての部分式は、右側のすべての部分式の前に評価されることに注意してください。A() * B()が残っC() / D()ているので、最初に発生します。

これはあなたの質問とは何の関係もありません。あなたの質問は誤解に基づいています。

上記の例でiが文字列に変換され、実際にコンパイルエラーが発生しない理由を知りたい

あなたの誤解があります。文字列に変換されてiません。に変換されていobjectます。あなたのプログラムは、次のものとまったく同じです。

   int i = 10;
   string k = "Test";
   string t1 = System.String.Concat((object)i, (string)k);
   Console.WriteLine(t1);
   string t2 = System.String.Concat((string)k, (object)i);
   Console.WriteLine(t2);

ご覧のとおり、そもそもiから文字列への変換はありません。iボクシング変換を介してオブジェクトに変換されてから、String.Concatメソッドに渡されます。次に、そのメソッドobject.ToString()はボックス化された整数を呼び出します。

つまり、次の前半を扱います。

上記の例でiが文字列に変換され、実際にコンパイルエラーが発生しない理由を知りたい

後半は、なぜコンパイルエラーがないのですか?

なぜコンパイルエラーが発生する必要があるのですか?C#仕様では、任意の文字列を任意のオブジェクトに追加したり、任意のオブジェクトを任意の文字列に追加したりできるとされています。intはオブジェクトであるため、文字列に追加できます。

于 2012-05-02T15:16:17.420 に答える
8

どちらの場合も、オペランドの1つ+として文字列を使用する演算子があります。オーバーロードされたユーザー定義演算子は含まれないため、コンパイラーはこれらの両方を文字列連結状況として使用します。

私の知る限り、C#コンパイラは、演算子などのユーザー定義のオーバーロードがある場合に、またはコンパイル時に式x + yであるシナリオでは、文字列連結のみを使用しません。 xystringXName operator +(XNamespace, string)

于 2012-05-02T13:57:12.567 に答える
0

実際、「+」演算子は連結用です。intとstringを連結すると、文字列が得られます(intをstringに自動的にキャストします)

于 2012-05-02T14:04:52.007 に答える