1

Dartについての私の理解は、この「キャスト」が実行時のセマンティクスに影響を与えるべきではないと信じるように導きますが、確認したかっただけです。

(foo as Bar).fee();
(foo as Bar).fi();
(foo as Bar).fo();

または、一度キャストするのが「ベストプラクティス」ですか。

final bFoo = (foo as Bar);
bFoo.fee();
bFoo.fi();
bFoo.fo();
4

3 に答える 3

3

これは、DartVMオプティマイザがケースを処理する方法に大きく依存します。Dartの最新バージョンを使用して、2つのテスト関数を作成しました。

void test1() {
  Dynamic bar = makeAFoo();

  for (int i = 0; i < 5000; i++) {
    (bar as Foo).a();
    (bar as Foo).b();
  }
}

void test2() {
  Dynamic bar = makeAFoo();

  Foo f = bar as Foo;
  for (int i = 0; i < 5000; i++) {
    f.a();
    f.b();
  }
}

test1の最適化されたコードを見ると、ループが次のようになっていることがわかります。

00D09A3C    bf813b9d00             mov edi,0x9d3b81  'instance of  Class: SubtypeTestCache'
00D09A41    57                     push edi
00D09A42    50                     push eax
00D09A43    6811003400             push 0x340011
00D09A48    e8d36c83ff             call 0x540720  [stub: Subtype1TestCache]
00D09A4D    58                     pop eax
00D09A4E    58                     pop eax
00D09A4F    5f                     pop edi
00D09A50    81f911003400           cmp ecx,0x340011
00D09A56    7411                   jz 0xd09a69
00D09A58    81f9710f7c00           cmp ecx,0x7c0f71
00D09A5E    0f8437000000           jz 0xd09a9b
00D09A64    e900000000             jmp 0xd09a69
00D09A69    8b1424                 mov edx,[esp]
00D09A6C    8b4c2404               mov ecx,[esp+0x4]
00D09A70    6811003400             push 0x340011
00D09A75    50                     push eax
00D09A76    68b9229d00             push 0x9d22b9
00D09A7B    51                     push ecx
00D09A7C    52                     push edx
00D09A7D    6889289d00             push 0x9d2889
00D09A82    b8813b9d00             mov eax,0x9d3b81  'instance of  Class: SubtypeTestCache'
00D09A87    50                     push eax
00D09A88    b9b0d00b00             mov ecx,0xbd0b0
00D09A8D    ba06000000             mov edx,0x6
00D09A92    e8896583ff             call 0x540020  [stub: CallToRuntime]
00D09A97    83c418                 add esp,0x18
00D09A9A    58                     pop eax
00D09A9B    5a                     pop edx
00D09A9C    59                     pop ecx
00D09A9D    50                     push eax
00D09A9E    a801                   test al,0x1
00D09AA0    0f8450010000           jz 0xd09bf6
00D09AA6    0fb74801               movzx_w ecx,[eax+0x1]
00D09AAA    81f922020000           cmp ecx,0x222
00D09AB0    0f8540010000           jnz 0xd09bf6
00D09AB6    b9d1229d00             mov ecx,0x9d22d1  'Function 'a':.'
00D09ABB    bae96ccb00             mov edx,0xcb6ce9  Array[1, 1, null]
00D09AC0    e82b6983ff             call 0x5403f0  [stub: CallStaticFunction]
00D09AC5    83c404                 add esp,0x4
00D09AC8    b911003400             mov ecx,0x340011
00D09ACD    ba11003400             mov edx,0x340011
00D09AD2    8b45f4                 mov eax,[ebp-0xc]
00D09AD5    51                     push ecx
00D09AD6    52                     push edx
00D09AD7    3d11003400             cmp eax, 0x340011
00D09ADC    0f849a000000           jz 0xd09b7c
00D09AE2    a801                   test al,0x1
00D09AE4    7505                   jnz 0xd09aeb
00D09AE6    e95f000000             jmp 0xd09b4a
00D09AEB    0fb74801               movzx_w ecx,[eax+0x1]
00D09AEF    81f922020000           cmp ecx,0x222
00D09AF5    0f8481000000           jz 0xd09b7c
00D09AFB    0fb77801               movzx_w edi,[eax+0x1]
00D09AFF    8b4e07                 mov ecx,[esi+0x7]
00D09B02    8b891c100000           mov ecx,[ecx+0x101c]
00D09B08    8b0cb9                 mov ecx,[ecx+edi*0x4]
00D09B0B    8b7927                 mov edi,[ecx+0x27]
00D09B0E    8b7f03                 mov edi,[edi+0x3]
00D09B11    81ff59229d00           cmp edi,0x9d2259
00D09B17    0f845f000000           jz 0xd09b7c
00D09B1D    bfd13b9d00             mov edi,0x9d3bd1  'instance of  Class: SubtypeTestCache'
00D09B22    57                     push edi
00D09B23    50                     push eax
00D09B24    6811003400             push 0x340011
00D09B29    e8f26b83ff             call 0x540720  [stub: Subtype1TestCache]
00D09B2E    58                     pop eax
00D09B2F    58                     pop eax
00D09B30    5f                     pop edi
00D09B31    81f911003400           cmp ecx,0x340011
00D09B37    7411                   jz 0xd09b4a
00D09B39    81f9710f7c00           cmp ecx,0x7c0f71
00D09B3F    0f8437000000           jz 0xd09b7c
00D09B45    e900000000             jmp 0xd09b4a
00D09B4A    8b1424                 mov edx,[esp]
00D09B4D    8b4c2404               mov ecx,[esp+0x4]
00D09B51    6811003400             push 0x340011
00D09B56    50                     push eax
00D09B57    68b9229d00             push 0x9d22b9
00D09B5C    51                     push ecx
00D09B5D    52                     push edx
00D09B5E    6889289d00             push 0x9d2889
00D09B63    b8d13b9d00             mov eax,0x9d3bd1  'instance of  Class: SubtypeTestCache'
00D09B68    50                     push eax
00D09B69    b9b0d00b00             mov ecx,0xbd0b0
00D09B6E    ba06000000             mov edx,0x6
00D09B73    e8a86483ff             call 0x540020  [stub: CallToRuntime]
00D09B78    83c418                 add esp,0x18
00D09B7B    58                     pop eax
00D09B7C    5a                     pop edx
00D09B7D    59                     pop ecx
00D09B7E    50                     push eax
00D09B7F    a801                   test al,0x1
00D09B81    0f8479000000           jz 0xd09c00
00D09B87    0fb74801               movzx_w ecx,[eax+0x1]
00D09B8B    81f922020000           cmp ecx,0x222
00D09B91    0f8569000000           jnz 0xd09c00
00D09B97    b961239d00             mov ecx,0x9d2361  'Function 'b':.'
00D09B9C    bae96ccb00             mov edx,0xcb6ce9  Array[1, 1, null]
00D09BA1    e84a6883ff             call 0x5403f0  [stub: CallStaticFunction]
00D09BA6    83c404                 add esp,0x4
00D09BA9    8b4df8                 mov ecx,[ebp-0x8]
00D09BAC    83c102                 add ecx,0x2
00D09BAF    0f8055000000           jo 0xd09c0a
00D09BB5    89cf                   mov edi,ecx
00D09BB7    8b5df4                 mov ebx,[ebp-0xc]
00D09BBA    e90efeffff             jmp 0xd099cd

そして、test2の最適化されたコードは、ループが次のようになっていることを確認できます。

00D09F3D    894df4                 mov [ebp-0xc],ecx
00D09F40    81f910270000           cmp ecx,0x2710
00D09F46    0f8d46000000           jnl 0xd09f92
00D09F4C    3b251c414700           cmp esp,[0x47411c]
00D09F52    0f8659000000           jna 0xd09fb1
00D09F58    50                     push eax
00D09F59    b9d1229d00             mov ecx,0x9d22d1  'Function 'a':.'
00D09F5E    bae96ccb00             mov edx,0xcb6ce9  Array[1, 1, null]
00D09F63    e8886483ff             call 0x5403f0  [stub: CallStaticFunction]
00D09F68    83c404                 add esp,0x4
00D09F6B    8b45f0                 mov eax,[ebp-0x10]
00D09F6E    50                     push eax
00D09F6F    b961239d00             mov ecx,0x9d2361  'Function 'b':.'
00D09F74    bae96ccb00             mov edx,0xcb6ce9  Array[1, 1, null]
00D09F79    e8726483ff             call 0x5403f0  [stub: CallStaticFunction]
00D09F7E    83c404                 add esp,0x4
00D09F81    8b4df4                 mov ecx,[ebp-0xc]
00D09F84    83c102                 add ecx,0x2
00D09F87    0f8048000000           jo 0xd09fd5
00D09F8D    8b45f0                 mov eax,[ebp-0x10]
00D09F90    ebab                   jmp 0xd09f3d

また、test1では2つではなく、SubTypeTestCache(test2のループ外)への呼び出しのセットは1つだけです。

現在、キャストを1回実行する方が高速であるように見えますが、キャストをループから引き出すことは、VMが将来実行する可能性のある単純な最適化のように見えます。

于 2012-09-13T16:03:11.967 に答える
2

実行(foo as Bar)には2つの効果があります。

  • これは、fooが静的型分析を支援し、エディターにコード補完を実行させるBarであることをエディターに通知します。
  • fooがBar(またはBarのサブタイプ)であることを確認します。そうでない場合は、CastExceptionをスローします。

(http://www.dartlang.org/docs/spec/latest/dart-language-specification.pdf)で「型キャスト」を探します。

更新:ジョンの答えも好きですが、もう1つ言うべきだと思います。あなたがキャストを1回と3回行うことについて話していたという事実を見落としました。を見てfinal bFoo = (foo as Bar);、言語セマンティクスについてもう1つ言いたいと思います。

Dart Editor、dart2js、およびVMは、fooがBar型であると推測できることは事実です。これにより、追加のチェックなどが節約されます。ただし、言語のセマンティクスは少し異なることを示しています。「finalbFoo」には型注釈がありません。したがって、言語仕様によれば、bFooはDynamic型です。

したがって、「(foo as Bar)」を3回記述すると、各式はBarになります。しかし、bFooを作成すると、Dynamicオブジェクトが作成されます。

于 2012-09-13T15:50:45.430 に答える
1

as同じ変数に対して3つのキャストを連続して実行することは「ベストプラクティス」ではありません。

asキャストは実際にはランタイムチェックです。推測しているだけですが、エディターからの警告を減らしたい場合は、おそらくもっと良い方法があります。

たとえば、次の1つのシナリオがあります。

class Foo {

}

class Bar extends Foo {
  m1() => print('m1');
}

doStuff(Foo foo) {
  foo.m1();  // warning here
}

main() {
  var foo = new Bar();
  doStuff(foo);
}

上記のコードは問題なく実行されますが、エディターには警告が表示されます。警告を排除するには、コードをリファクタリングすることをお勧めします。doStuffからFooアノテーションを削除するか、m1()をFooに移動することを検討するか、ダブルディスパッチを行うことができます。

于 2012-09-14T06:42:09.157 に答える