0

奇妙な振る舞いをしたので、それを理解したいと思います。しかし、私はウェブ上で良い答えを見つけていません:(

これが状況です。問題に焦点を当てるために名前とロジックを抽象化しました。A、B、C の 3 つの型を取得しました。B と C には、A オブジェクトに変換する暗黙の演算子が定義されています。

public class A
{
    public static implicit operator A(B input){ /* Convert B to A */ }
    public static implicit operator A(C input) { /* Convert C to A*/ }
}

public class B { }
public class C { }

次に、これを行うと、コードがコンパイルされて正常に動作します。

A myObject = null;
if (condition)
    myObject = new B();
else
    myObject = new C();

しかし、インラインifで同じロジックを書くと、エラーが発生しました:

A myObject = condition ? new B() : new C();

エラー :

Type of conditional expression cannot be determined because there is no implicit conversion between 'B' and 'C'

この動作について何か考えはありますか?

お時間をいただきありがとうございます。

よろしくお願いします。バグがないようにしてください。

4

4 に答える 4

0

?: 演算子 (C# リファレンス)のコメントを参照して ください。

first_expression と second_expression の型が同じであるか、一方の型から他方の型への暗黙的な変換が存在する必要があります。

于 2013-09-27T13:50:55.757 に答える
0

@Jon Skeet : 生成された MSIL を見た後、これが私が見つけたもので、非常に興味深いものです。テスト用に書いた2つのメソッドは次のとおりです。

static void ClassicalIf(bool condition)
{
    int i = 0;
    if (condition)
        i = 1;
    else
        i = 2;
}

static void InlineIf(bool condition)
{
    int i = condition ? 1 : 2;
}

ここにコメント付きの MSIL があるので、誰でも何が行われたか、インライン構文に暗黙の変換が必要な理由を理解できます。

インライン if の場合:

.method private hidebysig static void InlineIf(bool condition) cil managed
{
    .maxstack 1
    .locals init (
        [0] int32 i)
    L_0000: nop 
    L_0001: ldarg.0         -- Load argument '0' onto the stack
    L_0002: brtrue.s L_0007 -- Branch to L_0007 if value is non-zero
    L_0004: ldc.i4.2        -- Push 2 onto the stack
    L_0005: br.s L_0008     -- Branch to L_0008
    L_0007: ldc.i4.1        -- Push 1 onto the stack
    L_0008: nop 
    L_0009: stloc.0         -- Pop from stack into local variable 0
    L_000a: ret 
}

そして、これが「通常の」 if の場合です。

.method private hidebysig static void ClassicalIf(bool condition) cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 i,
        [1] bool CS$4$0000) -- Additional bool for if
    L_0000: nop 
    L_0001: ldc.i4.0        -- Push 0 onto the stack
    L_0002: stloc.0         -- Pop from stack into local variable '0'
    L_0003: ldarg.0         -- Load argument '0' onto the stack
    L_0004: ldc.i4.0        -- Push 0 onto the stack 
    L_0005: ceq             -- Push 1 if value1 equals value2 (on stack), else push 0.
    L_0007: stloc.1         -- Pop from stack into local variable '1'
    L_0008: ldloc.1         -- Load local variable '1' onto stack.
    L_0009: brtrue.s L_000f -- Branch to L_000f if value is non-zero
    L_000b: ldc.i4.1        -- Push 1 onto the stack 
    L_000c: stloc.0         -- Pop from stack into local variable '0'
    L_000d: br.s L_0011     -- Branch to L_0011
    L_000f: ldc.i4.2        -- Push 2 onto the stack 
    L_0010: stloc.0         -- Pop from stack into local variable '0'
    L_0011: ret 
}

そのため、可能であればインラインも使用しようとします。少ない命令 (つまり CPU) と少ないメモリ使用量。

于 2013-09-27T14:32:58.607 に答える